Mercurial > hg > audiostuff
diff intercom/g711/g711demo.c @ 2:13be24d74cd2
import intercom-0.4.1
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 09:57:52 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/intercom/g711/g711demo.c Fri Jun 25 09:57:52 2010 +0200 @@ -0,0 +1,459 @@ +/* 11.Apr.2000 v3.2 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + G711DEMO.C + + Description: + ~~~~~~~~~~~~ + Example-program for converting from linear samples to A/u law log + compression and vice-versa, according to ITU-T Rec.G711. + + Usage: + ~~~~~~ + $ g711demo [-?] [-r] [-skip skip] Law Transf InpFile OutFile + [BlockSize [1stBlock [NoOfBlocks]]] + + where: + Law is the law desired (either A or u) + Transf is the desired convertion on the input file: + [lili], linear to linear: lin -> (A/u)log -> lin + [lilo], linear to (A/u)-log + [loli], (A/u) log to linear + InpFile is the name of the file to be processed; + OutFile is the name with the compressed/expanded data; + BlockSize is the block size, in number of samples (16 -bit words) + (default is 256); + 1stBlock is the number of the first block of the input file + to be processed. (Default: 1) + NoOfBlocks is the number of blocks to be processed, starting on + block "1stBlock". (default is til end-of-file) + + Options: + -? display usage and quit. + -r disables even-bit swap by A-law encoding and decoding. + By default, even bits of the A-law samples ARE inverted + by alaw_compress() at return time, as well as by + alaw_expand() at its beginning. With the option + "-r", the log samples have NOT their even bits + inverted before being saved to disk NOR after + read from a file. + -skip is the number of samples to skip before the beginning + of the 1st block. + + Example: + $ G711 u lili voice.ref voice.rel 256 3 45 + + The command above takes the samples in file "voice.ref" and converts + them to A-law and back to linear, saving them into file "voice.rel", + starting at block 3 for 45 blocks, each block being 256 samples wide. + + Variables: + ~~~~~~~~~~ + law law to use (either A or u) + conv desired processing + inpfil input file name; + outfil output file name; + N block size; + N1 first block to filter; + N2 no. of blocks to filter; + + Compilation of Demo Program: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + The test program allows to process binary/ILS files of any size by + loading segments of data from/to file. The size of the working + segment must be entered. + + VAX/VMS: + $ CC G711 + $ link G711 + $ G711 :== $G711_Disk:[G711_Dir]G711 + $ G711 u lili ifile ofile 233 3 47 + + This command line invokes the u-law utility, converts from linear + over ulaw to linear. It processes the input file "ifile" by + loading segments of 233 samples and writes the result to "ofile", + from the 3rd segment, for 47 segments. + + Turbo-C, Turbo-C++: + > tcc G711 + > G711 a lilo ifile ofile 39 1 + + This command line invokes the a-law utility, converts from linear + to a-law. It processes the input file "ifile" by loading + segments of 39 samples and writes the result (alaw-samples) to + "ofile", starting from the beginning of the file. It will ask + the number of segments. + + HighC (MetaWare, version R2.32): + > hc386 G711.c + > Run386 G711 a loli ifile ofile 3333 + + This command line invokes the a-law utility, converts from a-law + to linear It processes the input file "ifile" (alaw-samples) by + loading segments of 3333 samples and writes the result (linear + samples) to "ofile". It will ask the starting segment and the + number of segments. + + SunC (SunOS - BSD Unix) + # cc -o g711demo g711demo.c + # g711demo a lilo ifile ofile 256 1 132 + + Exit values: + ~~~~~~~~~~~~ + 0 success (all but VMS); + 1 success (only in VMS); + 2 error opening input file; + 3 error creating output file; + 4 error moving pointer to desired start of conversion; + 5 error reading input file; + 6 error writing to file; + 7 invalid law + 8 invalid conversion + 10 error allocating memory + + Prototypes: + ~~~~~~~~~~~ + Needs ugstdemo.h and includes g711.h. + + Authors: + ~~~~~~~~ + Simao Ferraz de Campos Neto Rudolf Hofmann + CPqD/Telebras PHILIPS KOMMUNIKATIONS INDUSTRIE AG + DDS/Pr.11 Kommunikationssysteme + Rd. Mogi Mirim-Campinas Km.118 Thurn-und-Taxis-Strasse 14 + 13.080-061 - Campinas - SP (Brazil) D-8500 Nuernberg 10 (Germany) + + Phone : +55-192-39-6637 Phone : +49-911-526-2603 + FAX : +55-192-39-2179 FAX : +49-911-526-3385 + EMail : tdsimao@cpqd.ansp.br EMail : hf@pkinbg.uucp + + History: + ~~~~~~~~ + 07.Feb.1991 v1.0 Release of 1st demo program for G711 module (CPqD). + 10.Dec.1991 v2.0 Demo program incorporated in G711 module and + rebuild by PKI. + 08.Feb.1992 v2.1 Demo separated from module file; ILS header + manipulation removed; low level I/O; changes to + assure compatibility with Unix (SunOS). + 14.Apr.1993 v3.0 Inclusion of display_usage() and of option "-r" + <tdsimao@venus.cpqd.ansp.br> + 22.Feb.1996 v3.1 Removed compilation warnings, included headers as + suggested by Kirchherr (FI/DBP Telekom) to run under + OpenVMS/AXP <simao@ctd.comsat.com> + 11.Apr.2000 v3.2 Corrected bug that made incorrect calculation on + total number of blocks to process when the block + size is not a multiple of the file + size. <simao.campos@labs.comsat.com> + 13jan2005 Byte for compressed data + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include "ugstdemo.h" /* UGST defines for demo programs */ + +/* Include general headers */ +#include <stdio.h> /* UNIX Standard I/O Definitions */ +#include <ctype.h> /* Character Type Classification */ +#include <string.h> /* String handling functions */ +#include <stdlib.h> /* General utility definitions */ +#include <math.h> + +/* Include OS dependent headers */ +#if defined(VMS) +#include <stat.h> +#else /* Others */ +#include <sys/stat.h> +#endif + + +/* G711 module functions */ +#include "g711.h" + + +/* + -------------------------------------------------------------------------- + void display_usage() + + Displays usage of the program. Upon completion, aborts the program. + + Created by <tdsimao@cpqd.ansp.br>, 14.Apr.93 + + -------------------------------------------------------------------------- +*/ +#define FP(x) fprintf(stderr, x) +void display_usage() +{ + FP("\n G711DEMO.C --- Version v3.2 of 11.Apr.2000 \n"); + FP("\n"); + FP(" Description:\n"); + FP(" ~~~~~~~~~~~~\n"); + FP(" Example-program for converting from linear samples to A/u law log\n"); + FP(" compression and vice-versa, according to ITU-T Rec.G711.\n"); + FP("\n"); + FP(" Usage:\n"); + FP(" ~~~~~~\n"); + FP(" $ G711 [-r] Law Transf InpFile OutFile BlkSize 1stBlock NoOfBlocks\n"); + FP("\n"); + FP(" where:\n"); + FP(" Law is the law desired (either A or u)\n"); + FP(" Transf is the desired convertion on the input file:\n"); + FP(" [lili], linear to linear: lin -> (A/u)log -> lin\n"); + FP(" [lilo], linear to (A/u)-log\n"); + FP(" [loli], (A/u) log to linear\n"); + FP(" InpFile is the name of the file to be processed;\n"); + FP(" OutFile is the name with the compressed/expanded data;\n"); + FP(" BlkSize is number of samples per block [256];\n"); + FP(" 1stBlock is the number of the first block of the input file\n"); + FP(" to be processed [1].\n"); + FP(" NoOfBlocks is the number of blocks to be processed, starting on\n"); + FP(" block `1stBlock'. Default is til end-of-file.\n"); + FP("\n"); + FP(" Options:\n"); + FP(" -? displays this message.\n"); + FP(" -r disables even-bit swap by A-law encoding and decoding.\n"); + FP(" -skip is the number of samples to skip.\n"); + FP("\n"); + + /* Quit program */ + exit(1); +} + +#undef FP +/* ..................... End of display_usage() .......................... */ + + +/* + ************************************************************************** + *** *** + *** Demo-Program for testing the correct implementation *** + *** and to show how to use the programs *** + *** *** + ************************************************************************** +*/ +int main(argc, argv) +int argc; +char *argv[]; +{ + long i, N, N1, N2, smpno, tot_smpno, cur_blk; + short *lin_buff; /* linear input samples */ + Byte *log_buff; /* compressed data */ + short *lon_buff; /* quantized output samples */ + char inpfil[127], outfil[127]; + FILE *Fi, *Fo; + int inp, out; + char law[4], lilo[8]; + short inp_type, out_type; + char revert_even_bits = 1; + clock_t t1, t2; /* aux. for CPU-time measurement */ +#ifdef VMS + char mrs[15]; /* for correct mrs in VMS environment */ +#endif + long start_byte, skip = 0; + +/* + * GETTING PARAMETERS + */ + /* Get options */ + if (argc < 2) + display_usage(); + else { + while (argc > 1 && argv[1][0] == '-') + if (argv[1][1] == 'r') { + /* Disable revertion of even bits */ + revert_even_bits = 0; + + /* Move argv over the option to the 1st mandatory argument */ + argv++; + + /* Update argc */ + argc--; + } else if (strcmp(argv[1], "-skip") == 0) { + /* Get skip length */ + skip = atol(argv[2]); + + /* Check bounds */ + if (skip < 0) { + fprintf(stderr, "Skip has to be > 0!\n"); + exit(10); + } + + /* Move argv over the option to the next argument */ + argv += 2; + + /* Update argc */ + argc -= 2; + } else if (argv[1][1] == '?') { + /* Display intructions */ + display_usage(); + } else { + fprintf(stderr, + "ERROR! Invalid option \"%s\" in command line\n\n", argv[1]); + display_usage(); + } + } + + + /* Get parameters */ + GET_PAR_S(1, "_Law (A, u): ................. ", law); + GET_PAR_S(2, "_Transf (lili,lilo,loli): .... ", lilo); + GET_PAR_S(3, "_File to be converted: ....... ", inpfil); + GET_PAR_S(4, "_Output File: ................ ", outfil); + FIND_PAR_L(5, "_Block Length: ............... ", N, 256); + FIND_PAR_L(6, "_Start Block: ................ ", N1, 1); + FIND_PAR_L(7, "_No. of Blocks: .............. ", N2, 0); + + + /* ......... SOME INITIALIZATIONS ......... */ + --N1; + + /* Classification of the conversion desired */ + inp_type = toupper(lilo[1]) == 'O' ? IS_LOG : IS_LIN; + out_type = toupper(lilo[3]) == 'O' ? IS_LOG : IS_LIN; + if ((out_type == IS_LOG) && (inp_type == IS_LOG)) + HARAKIRI("log. to log. makes no sense! Aborted...\n", 8); + + /* Classification of law */ + law[0] = toupper(law[0]); + if ((law[0] != (char) 'A') && (law[0] != (char) 'U')) + HARAKIRI(" Invalid law!\n", 7); + + /* .......... ALLOCATION OF BUFFERS .......... */ + + if ((lin_buff = (short *) calloc(N, sizeof(short))) == NULL) + HARAKIRI("Can't allocate memory for input buffer\n", 10); + + if ((log_buff = (Byte *) calloc(N, sizeof(Byte))) == NULL) + HARAKIRI("Can't allocate memory for output buffer\n", 10); + + if ((lon_buff = (short *) calloc(N, sizeof(short))) == NULL) + HARAKIRI("Can't allocate memory for temporary buffer\n", 10); + + + /* .......... FILE OPERATIONS .......... */ + +#ifdef VMS + sprintf(mrs, "mrs=%d", 2 * N); +#endif + + /* Open input file */ + if ((Fi = fopen(inpfil, RB)) == NULL) + KILL(inpfil, 2); + inp = fileno(Fi); + + /* Open (create) output file */ + if ((Fo = fopen(outfil, WB)) == NULL) + KILL(outfil, 3); + out = fileno(Fo); + + /* Define starting byte in file */ + start_byte = (N1 * N + skip) * sizeof(short); + + /* ... and move file's pointer to 1st desired block */ + if (fseek(Fi, (N1 * N + skip) * sizeof(short), 0) < 0l) + KILL(inpfil, 4); + + /* Check whether is to process til end-of-file */ + if (N2 == 0) { + struct stat st; + /* ... hey, need to skip the delayed samples! ... */ + stat(inpfil, &st); + N2 = ceil((st.st_size - start_byte) / (double) (N * sizeof(short))); + } + + +/* + * ......... COMPRESSION/EXPANSION ......... + */ + t1 = clock(); /* measure CPU-time */ + tot_smpno = 0; + + switch (law[0]) { + /* ......... Process A-law rule ......... */ + case 'A': + + /* Input: LINEAR | Output: LOG */ + if (inp_type == IS_LIN && out_type == IS_LOG) + for (tot_smpno = cur_blk = 0; cur_blk < N2; + cur_blk++, tot_smpno += smpno) { + if ((smpno = fread(lin_buff, sizeof(short), N, Fi)) < 0) + KILL(inpfil, 5); + alaw_compress(smpno, lin_buff, log_buff); + if (!revert_even_bits) + for (i = 0; i < smpno; i++) + log_buff[i] ^= 0x0055; + + if ((smpno = fwrite(log_buff, sizeof(Byte), smpno, Fo)) < 0) + KILL(outfil, 6); + } + + /* Input: LINEAR | Output: LINEAR */ + else if (inp_type == IS_LIN && out_type == IS_LIN) + for (tot_smpno = cur_blk = 0; cur_blk < N2; + cur_blk++, tot_smpno += smpno) { + if ((smpno = fread(lin_buff, sizeof(short), N, Fi)) < 0) + KILL(inpfil, 5); + alaw_compress(smpno, lin_buff, log_buff); + alaw_expand(smpno, log_buff, lon_buff); + if ((smpno = fwrite(lon_buff, sizeof(short), smpno, Fo)) < 0) + KILL(outfil, 6); + } + + /* Input: LOG | Output: LINEAR */ + else if (inp_type == IS_LOG) + for (tot_smpno = cur_blk = 0; cur_blk < N2; + cur_blk++, tot_smpno += smpno) { + if ((smpno = fread(log_buff, sizeof(Byte), N, Fi)) < 0) + KILL(inpfil, 5); + if (!revert_even_bits) + for (i = 0; i < smpno; i++) + log_buff[i] ^= 0x0055; + alaw_expand(smpno, log_buff, lon_buff); + if ((smpno = fwrite(lon_buff, sizeof(short), smpno, Fo)) < 0) + KILL(outfil, 6); + } + break; + + /* ......... Process u-law rule ......... */ + + case 'U': + /* Input: LINEAR | Output: LOG */ + if (inp_type == IS_LIN && out_type == IS_LOG) + for (tot_smpno = cur_blk = 0; cur_blk < N2; + cur_blk++, tot_smpno += smpno) { + smpno = fread(lin_buff, sizeof(short), N, Fi); + ulaw_compress(smpno, lin_buff, log_buff); + smpno = fwrite(log_buff, sizeof(Byte), smpno, Fo); + } + + /* Input: LINEAR | Output: LINEAR */ + else if (inp_type == IS_LIN && out_type == IS_LIN) + for (tot_smpno = cur_blk = 0; cur_blk < N2; + cur_blk++, tot_smpno += smpno) { + smpno = fread(lin_buff, sizeof(short), N, Fi); + ulaw_compress(smpno, lin_buff, log_buff); + ulaw_expand(smpno, log_buff, lon_buff); + smpno = fwrite(lon_buff, sizeof(short), smpno, Fo); + } + + /* Input: LOG | Output: LINEAR */ + else if (inp_type == IS_LOG) + for (tot_smpno = cur_blk = 0; cur_blk < N2; + cur_blk++, tot_smpno += smpno) { + smpno = fread(log_buff, sizeof(Byte), N, Fi); + ulaw_expand(smpno, log_buff, lon_buff); + smpno = fwrite(lon_buff, sizeof(short), smpno, Fo); + } + break; + } + + + /* ......... FINALIZATIONS ......... */ + + t2 = clock(); + printf("Speed: %f sec CPU-time for %ld processed samples\n", + (t2 - t1) / (double) CLOCKS_PER_SEC, tot_smpno); + + fclose(Fi); + fclose(Fo); +#ifndef VMS + return (0); +#endif +}