📄 sv56demo.c
字号:
/* v3.4 08.Jul.99 ============================================================================ SV56DEMO.C ~~~~~~~~~~ Description: ~~~~~~~~~~~~ Example program that calculates the factor for equalizing, and equalizes, a file's active speech level "NdB" dBs below a 0 dB reference. Here, the default reference is 0 dB below system overload. This program, as an option, may normalize the output file using the measure RMS (long term) level, instead of the active speech level. The calculation of speech file's active power uses the algorithm in ITU-T Recommendation P.56, and as a by-product of this mudule, also calculates the activity [%], RMS power, positive and negative peaks for the file, and peak factors. In general, input and output files are in integer represent- ation, 16-bit words, 2's complement. In UGST convention, this data must be left-adjusted, RATHER than right-adjusted. Since the speech voltmeter uses `float' input data, it is necessary to convert from short (in the mentioned format) to float; this is carried out by the function `sh2fl()'. This function has the option of `normalize' the input data to the range -1..+1, what is done. After the equalization factor is found, the function `scale()' is called to carry out the equalization using single (rather than double) float precision. After equalized, data need to be converted back to integer (short, right-justified). This is done by function `fl2sh()', using: truncation, no zero-padding of the least significant bits, left-justification of data, hard-clipping of data outside the range -32768..+32767. After that, data is saved to file. The default values for the AD,DA systems resolution is 16 bits, for the sampling rate is 16000 Hz. To change this on-line, just specify the parameters 6 and/or 7 conveniently in the command line. For example, 14 bits and 8000 Hz: $ sv56demo filein fileout 256 1 100 -15 8000 14 Usage: ~~~~~~ $ sv56demo [-options] FileIn FileOut [BlockSize [1stBlock [NoOfBlocks [DesiredLevel [SampleRate [Resolution] ] ] ] ] ] where: FileIn is the input file to be analysed and equalized; FileOut is the output equalized file BlockSize is the block size in number of samples; 1stBlock the first block to be analysed/equalized NoOfBlocks number of blocks to be analysed/equalized DesiredLevel level desired to the output file, in dBov or dBm0 SampleRate sampling rate used for acquiring/generating the file, in Hertz; default is 16000 Hz; THIS PARAMETER IS OPTIONAL! Resolution the digital system resolution (AD,DA systems), in number of bits; default to 16 bits; THIS PARAMETER IS OPTIONAL, but to specify it you need to specify the former one! Options: ~~~~~~~~ -bits n ........ change the default word length to n bits; equivalent to parameter Resolution above [default: 16 bits] -lev ndB ....... equivalent to specifying DesiredLevel above, just that here do not need to specify the former 3 parameters. -log file ...... print the statistics log into file rather than stdout -q ............. quit operation - does not print the progress flag. Saves time and avoids trash in batch processings. -qq ............ print short statistics summary; no progress flag. -rms ........... normalizes the output file using the RMS long-term level, instead of the active speech level. -sf f .......... set sampling frequency to `f' Hz; equivalent to parameter SampleRate above. -blk len ...... is the block size in number of samples; this parameter is optional, and the default is block size of 256 samples; equivalent to parameter N above -start sb ...... define `sb' as the first block to be measured; equivalent to parameter N1 above [default: first block of the file] -end eb ........ define `eb' as the last block to be measured -n nb .......... define `nb' as the number of blocks to be measured; equivalent to parameter N2 above [default: whole file] Modules used: ~~~~~~~~~~~~~ > sv-P56.c: contains the functions related to active speech level measurement according to P.56, init_speech_voltmeter(), speech_voltmeter() and bin_interp(). Their prototypesare in `sv-p56.h'. > ugst-utl.c: utility functions; here are used the gain/loss (scaling) algorithm of scale() and the data type conversion functions sh2fl() and fl2sh(). Prototypes are in `ugst-utl.h'. 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; Compilation: ~~~~~~~~~~~~ VaxC: cc sv56demo.c link sv56demo TurboC: tcc sv56demo.c Sun-OS: cc -o sv56demo sv56demo.c -lm Author: ~~~~~~~ Simao Ferraz de Campos Neto DDS/Pr11 Tel: +55-192-39-1396 CPqD/Telebras Fax: +55-192-53-4754 13085-061 Campinas SP Brazil E-mail: <tdsimao@venus.cpqd.ansp.br> Log of changes: ~~~~~~~~~~~~~~~ 09.Mar.90 0.0 Release of first version of a C speech voltmeter. 08.Oct.91 1.0 Release of demo program for the speech voltmeter module. 19.Feb.92 2.0 Call to module using state variable instead of individual variables. Compilation option between dB(overload) and dBm0. 18.May.92 2.1 Removed references to dBm0; input data is converted to the normalized range; speech voltmeter needs input data in normalized range. <tdsimao@cpqd.ansp.br> 10.Dec.94 3.0 Included additional input interface. NdB promoted from long to double. <simao@ctd.comsat.com> 21.Aug.95 3.1 Included additional option to normalize output file using RMS long-term level instead of active level, and options for block size, first block, last block, number of blocks. <simao@ctd.comsat.com> 29.May.97 3.2 moved summary statistics code to a function, and created a short summary function as well. Added command-line option to print short summary (-qq). Add -log option so save statistical summaries into a file <simao> 06.Apr.98 3.3 solved small bug that occurred when the file size was not a multiple of the frame size. The program was truncating the output file size to a multiple of the current block size. The fix was to introduce a ceil() in the calculation of N2 when N2==0 <simao> 08.Jul.99 3.4 fixed a bug in fwrite() call in main(); was saving N samples, rather than "l". This was causing more samples to be written to the end of the file when the file size was not a multiple of the block size <simao>. ============================================================================*//* ... Include for all UGST demos -- should be the 1st include ... */#include "ugstdemo.h"/* ... Includes in general ... */#include <stdio.h>#include <stdlib.h>#include <string.h> /* for strstr() */#include <math.h>/* ... Includes for O.S. specific headers ... */#if defined(VMS)#include <perror.h>#include <file.h>#include <stat.h>#else /* Unix/DOS */#include <sys/stat.h>#if defined(MSDOS)#include <fcntl.h>#include <io.h>#endif /* MSDOS */#endif /* !VMS *//* ... Include of speech-voltmeter-related routines ... */#include "sv-p56.h"/* ... Include of utilities ... */#include "ugst-utl.h"/* Local definitions */#define MIN_LOG_OFFSET 1.0e-20 /*To avoid sigularity with log(0.0) *//* ------------------------------------------------------------------------- void display_usage(void); ~~~~~~~~~~~~~~~~~~ Display proper usage for the demo program. Generated automatically from program documentation. History:~~~~~~~~ 10.Dec.94 v1.0 Created. <simao> -------------------------------------------------------------------------*/#define P(x) printf xvoid display_usage(){ P(("SV56DEMO.C: Version 3.4 of 08/Jul/1999 \n\n")); P((" Program to level-equalize a speech file \"NdB\" dBs below\n")); P((" the overload point for a linear n-bit (default: 16 bit) system.\n")); P((" using the P.56 speech voltmeter algorithm.\n")); P(("\n")); P((" Usage:\n")); P((" $ sv56demo [-options] FileIn FileOut \n")); P((" [BlockSize [1stBlock [NoOfBlocks [DesiredLevel\n")); P((" [SampleRate [Resolution] ] ] ] ] ]\n")); P((" FileIn: ..... is the input file to be analysed and equalized;\n")); P((" FileOut: .... is the output equalized file\n")); P((" BlockSize: .. is the block size [default: 256 samples]\n")); P((" 1stBlock: ... the first block to be manipulated [default: 1st]\n")); P((" NoOfBlocks: . number of blocks to be manipulated [default: all]\n")); P((" DesiredLevel: level desired to the output file, in dBov\n")); P((" [default: -26 dBov].\n")); P((" SampleRate: . sampling rate used for acquiring/generating the\n")); P((" file, in Hertz [default: 16000 Hz].\n")); P((" Resolution: . the digital system resolution (AD,DA systems), in\n")); P((" number of bits [default: 16 bits].\n")); P((" Options:\n")); P((" -lev ndB .... equivalent to specifying DesiredLevel above, but\n")); P((" here don't need to specify the former 3 parameters.\n")); P((" -sf f ....... set sampling frequency to `f' Hz; equivalent to\n")); P((" parameter SampleRate above.\n")); P((" -bits n ..... change the default word length to n bits; \n")); P((" equivalent to parameter Resolution.\n")); P((" -rms ........ normalizes the output file using the RMS long-term \n")); P((" level, instead of the active speech level.\n")); P((" -blk len .... is the block size in number of samples;\n")); P((" this parameter is optional [default is block size\n")); P((" of 256 samples]. Equiv. to param. BlockSize above\n")); P((" -start sb ... define `sb' the first block to be measured; equiv.\n")); P((" to param. 1stBlock above [dft: 1st block of file]\n")); P((" -end eb ..... define `eb' as the last block to be measured\n")); P((" -n nb ....... define `nb' as the number of blocks to be measured;\n")); P((" equiv. to param.NoOfBlocks above [dft: whole file]\n")); P((" -log file ... log statistics into file rather than stdout\n")); P((" -q .......... quiet operation - does not print the progress flag.\n")); P((" Saves time and avoids trash in batch processings.\n")); P((" -qq ......... print short statistics summary; no progress flag.\n")); /* Quit program */ exit(-128);}#undef P/* .................... End of display_usage() ........................... *//* ============================================================================ void print_p56_long_summary(char *file, SVP56_state state, double al_dB, ~~~~~~~~~~~~~~~~~~~~~~~~~~~ double NdB, double gain, double ratio, long N, long N1, long N2, long bitno); Print full summary of P.56 statistics Parameter: ~~~~~~~~~~ file ..... File name state .... P.56 state variable al_dB .... active level in dB NdB ...... desired dB level for output gain ..... gain to equalize file to desired level ratio .... ratio of maximum number representable in the system (based on the number of bits, or resolution, of the input speech file) to the range of the input signal. E.g., for a 16 bit system with a +-1 signal range, ratio = 32760 / 1.0. N ........ number of samples per block N1 ....... number of first block processed in the file N2 ....... total number of blocks processed from the file bitno .... number of bits per sample (input signal resolution) Returns ~~~~~~~ None Original author ~~~~~~~~~~~~~~~ simao@ctd.comsat.com Log of changes ~~~~~~~~~~~~~~ 01.Nov.96 v1.0 Creation. ============================================================================*/void print_p56_long_summary(out, file, state, al_dB, NdB, ratio, gain, N, N1, N2, bitno) FILE *out; SVP56_state state; char *file; double ratio, gain, al_dB, NdB; long N, N1, N2, bitno;{ static char unity[5] = "dBov"; double abs_max_dB, max_gain, new_max; /* Calculate peak in dB */ abs_max_dB = 20 * log10(SVP56_get_abs_max(state) + MIN_LOG_OFFSET) - state.refdB; /* Computes the maximum gain that will not cause saturation */ max_gain = al_dB - 20 * log10(SVP56_get_abs_max(state)); /* Print the relevant messages */ fprintf(out, "%s%s", " ---------------------------", "----------------------------"); fprintf(out, "\n Input file: ................... %s, ", file); fprintf(out, "%2ld bits, fs=%5.0f Hz", bitno, state.f); fprintf(out, "\n Block Length: ................. %7ld [samples]", N); fprintf(out, "\n Starting Block: ............... %7ld []", N1 + 1); fprintf(out, "\n Number of Blocks: ............. %7ld []", N2); fprintf(out, "\n %s desired for output: ...... %7.3f [%s]", unity, NdB, unity); /* Skip if filesize is zero */ if (state.n==0) { fprintf(out, "%s%s", "\n -***-----------------------", "----------------------------\n"); return; } /* If the activity factor is 0, don't report many things */ if (SVP56_get_activity(state) == 0) { fprintf(out, "\n Activity factor is ZERO -- the file is silence"); fprintf(out, " or idle noise"); fprintf(out, "%s%s", "\n ---------------------------", "----------------------------"); fprintf(out, "\n DC level: ..................... %7.0f [PCM]", ratio * SVP56_get_DC_level(state)); fprintf(out, "\n Maximum positive value: ....... %7.0f [PCM]", ratio * SVP56_get_pos_max(state)); fprintf(out, "\n Maximum negative value: ....... %7.0f [PCM]", ratio * SVP56_get_neg_max(state)); fprintf(out, "%s%s", "\n ---------------------------", "----------------------------"); fprintf(out, "\n Noise/silence energy (rms): ... %7.3f [dB]", SVP56_get_rms_dB(state)); } else { fprintf(out, "\n Norm factor desired is: ....... %7.3f [times]", gain); fprintf(out, "\n Max norm WITHOUT saturation: .. %7.3f [%s]", max_gain, unity); fprintf(out, "%s%s", "\n ---------------------------", "----------------------------"); fprintf(out, "\n DC level: ..................... %7.0f [PCM]", ratio * SVP56_get_DC_level(state)); fprintf(out, "\n Maximum positive value: ....... %7.0f [PCM]", ratio * SVP56_get_pos_max(state)); fprintf(out, "\n Maximum negative value: ....... %7.0f [PCM]", ratio * SVP56_get_neg_max(state)); fprintf(out, "%s%s", "\n ---------------------------", "----------------------------"); fprintf(out, "\n Long term energy (rms): ....... %7.3f [%s]", SVP56_get_rms_dB(state), unity); fprintf(out, "\n Active speech level: .......... %7.3f [%s]", al_dB, unity); fprintf(out, "\n RMS peak-factor found: ........ %7.3f [dB]", abs_max_dB - SVP56_get_rms_dB(state)); fprintf(out, "\n Active peak factor found: ..... %7.3f [dB]", abs_max_dB - al_dB); fprintf(out, "\n Activity factor: .............. %7.3f [%%]", SVP56_get_activity(state)); } fprintf(out, "%s%s", "\n ---------------------------", "----------------------------"); /* Tests if the equalization will cause saturation */ new_max = SVP56_get_abs_max(state) * gain; if (new_max > 1.0) { /* Print message */ fprintf(out, "\n%%SV-W-SAT, the dB level chosen causes SATURATION: "); fprintf(out, "old max=%5.0f; new max=%6.0f", ratio * SVP56_get_abs_max(state), ratio * new_max); fprintf(out, "\n%%SV-I-MAXLEVDB, the maximum norm factor "); fprintf(out, "to PREVENT clipping is %7.3fdB; ", max_gain); fprintf(out, "\n -------------------------------------------------------");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -