SPLIB
A signal processing library for C++

 

 

 


 

 

 

 

 

 


Ver 1.1  99-01-01 Thomas Eriksson

 

 


SPLIB A signal processing library for C++                                                 1

Introduction to SPLIB                                                                                                                                                             3

Why use SPLIB                                                                                                                                                                     3

How to use SPLIB                                                                                                                                                                 3

How to read the documentation                                                                                                                                         3

Basic functions and classes                                                                                                                                                   4

Vectors and  matrices                                                                                                                                                              6

Math                                                                                                                                                                                            8

Signal processing                                                                                                                                                                    9

Speech processing                                                                                                                                                                 10

Quantization                                                                                                                                                                           11

MATLAB engine                                                                                                                                                                    12

Examples                                                                                                                                                                                  13

Basic functions and classes                                                                                                                                              13

Vectors                                                                                                                                                                                  13

Matrices                                                                                                                                                                                13

MATH                                                                                                                                                                                  14

Signal processing                                                                                                                                                                14

Speech processing                                                                                                                                                              14

Quantization                                                                                                                                                                         14

MATLAB engine                                                                                                                                                                15

Full example (a very simple LPC-based speech coder)                                                                                                  15

Frequently asked questions                                                                                                                                                 17

 

Introduction to SPLIB

SPLIB is a signal processing library for C++. It has been compiled with the CC compiler on SGI workstations, with the gcc compiler on SGI and Linux machines, with the Borland C++ Builder and  Microsoft Visual C++ compiler under Windows 95, 98 and NT, but it should also compile under most C++ compilers with support for templates. SPLIB is slightly biased towards processing of speech signals, but it also contains a lot of general signal processing classes and functions. The functions are written to be as similar to MATLAB as possible, with the same function names and parameters. The fvec class (vec<float>, see below; a vector of floats) is the most important class of the library, and most of the signal processing functions accept this class as parameter.

Why use SPLIB

Reasons to use SPLIB:

·         You get access to a lot of signal processing software.

·         All the functions are extensively debugged by several people.

·         SPLIB works well together with MATLAB, and many functions are identical to their MATLAB counterpart.

How to use SPLIB

To use SPLIB, just add the line

#include <sp.h>

to the beginning of your program.

 

For UNIX computers:

In the makefile, the path to the include files must be given. This is done by adding

-I/{path to splib source code}

as an argument to the compiler. You must also tell the linker where it can find the SPLIB library, and the MATLAB library if the MATLAB engine is used.

Add

/{path to splib library}/libsp.a

for the SPLIB library, and

/{path to splib library}/libmat.a

for the MATLAB library (if you want to work with the MATLAB engine). An example makefile follows:

 

.SUFFIXES : .o .cpp

SPLIB=/usr/eriksson/splib/libsp.a

MLIB=/usr/common/apps/matlab/extern/lib/sgi/libmat.a

myprog: myprog.o

                 $(CC) -o myprog myprog.o $(SPLIB) $(MLIB) -lm

.cpp.o:

                 $(CC) -I/usr/eriksson/clib/SPLIB -o $*.o -c $*.cpp

 

(the .SUFFIXES line is included so that the make command can understand what to do with files with extension .cpp).

 

For Microsoft Windows computers:

 

How to read the documentation

It is possible to use most of the functions in the SPLIB library without any knowledge of C++, but for full understanding, basic knowledge of C++ is required.

The most important class in the library is vec<float>, or equivalently, fvec, since the signal processing functions depends heavily on this class for accepting and returning parameters. Therefore, understanding this class is required knowledge to understand the other classes and functions. The fvec class can be used much as the standard C array float[], but the memory is dynamically allocated; the size of the vector need not be known at compile time.

Other important classes are fmat (matrices), string (a string class), bifstream and bofstream (classes for reading and writing binary files). For signal processing, the classes arfilter and mafilter (AR and MA filters) are useful for filtering, GaussRV is a class for generating Gaussian random numbers, and sq and vq are classes for scalar and vector quantization, respectively.

In the following, classes are indicated by underlining (class), and after the general description of the class there is a description of the constructors and methods of the class.

Basic functions and classes

(bfstream.h, comp.h, timing.h, str.h, parser.h, debug.h)

The basic routines includes routines for handling binary files, complex numbers, strings, etc.

bifstream, bofstream

Handles binary input and output files.

bifstream::bifstream(string), bifstream::bifstream(), bofstream::bofstream(string), bofstream::bofstream()

Constructors for bifstream and bofstream, with or without a file name argument.

bifstream::open(string), bofstream::open(string), bifstream::close(), bofstream::close()

Member functions to open and close files for input/output.

bifstream::operator>>

Reads data from the input file. Data may be of any built-in type, or of type vec<>.

bifstream::eof()

Returns true if end-of-file.

bofstream::operator<<

Reads data from the input file. Data may be of any built-in type, or of type vec<>.

complex

Complex numbers.

parser

This class is useful for handling setup files. The argument gives the name of a file with setup lines.

parser::parser(string), parser::parser(int,char**), parser::parser(string,int,char**)

Constructors. The string argument is the name of the setup file. The int and char** arguments are number of command line arguments, and command line argument strings, respectively, to read setup data from the command line. If both a file name and command line arguments are given, and the same setup variable exists in both, the command line takes precedence.

parser::getstr(string), parser::getint(string), parser::getreal(string), parser::getstr(string,long), parser::getint(string,long), parser::getreal(string,long)

Functions to get setup parameters from a setup file.

string

Strings.

string::left(int), string::right(int), string::mid(int,int), string::length(),string::pos(char*), string::str2num(), string::split(int), string::operator+, string::operator==, string::operator!=, string::operator<, string::operator>, string::operator[], string::operator<<, string::operator char*()

Various functions and operators to handle the string class

timer

A class for timing purposes.

timer::timer()

Constructor.

timer::start(), timer::stop(), timer::reset(), timer::gettime()

Functions to start, stop, reset and get the elapsed time.

errorif(condition,text)

A function to check a condition, and abort with a message if condition is true.

tic(), toc()

Functions for timing purposes. tic() starts the timer, toc() returns the elapsed time.

Vectors and  matrices

(vec.h, mat.h, elmat.h)

 

vec<>

A templated vector class.

fvec, dvec, cvec, lvec, svec

Typedefs for the templated vec<> class. fvec=vec<float>, dvec=vec<double>, cvec=vec<complex>, lvec=vec<long>, svec=vec<short>.

vec::vec(), vec::vec(long)

Constructors to define a vector with length zero, or length given by the long argument. Note that no initialization of the vector occurs; the elements must be manually zeroed if required (see vec::clear()).

vec::length(), vec::setlength(long)

Sets and get length of a vector.

vec::clear()

Sets all element to 0.

vec::ptr()

Returns pointer to the first element in the vector. This makes it possible to use the vector as a standard C array.

vec::right(long), vec::left(long), vec::mid(long,long)

Returns right, left or center part of vector. For right and left, a single argument gives the number of elements in the returned vector. mid has two arguments, the first is the starting position and the second is the number of elements.

vec::del(long), vec::ins(long, float), vec::replacemid(long, vec<>)

Deletes or inserts data in vector. The first argument is the position in the vector.

vec::load(string), vec::save(string), vec::loadascii(string), vec::saveascii(fname)

Loads and save vector from/to file, in binary or ascii format.

sum(fvec), prod(fvec), mean(fvec), median(fvec), geometricmean(fvec), variance(fvec)

Statistical/mathematical functions with a single vec<float> as argument. Returns a float.

zeros(long), ones(long), impulse(long), randu(long), randn(long), hamming(long)

These functions returns a vec<float> filled with data. The functions have a single argument: the length of the returned vector. randu returns uniformly distribute data on the interval [0,1[, randn returns Gaussian data.

sort(fvec), sortindex(fvec)

Sorts a vector in ascending order. sort returns the sorted vector, sortindex returns a vector with indices to the elements of the vector, with the index to the smallest element at pos 0 etc.

operator+, operator-, operator*, operator/, operator+=, operator-=, operator*=, operator/=

Operators for mathematical operations on vec<float> and vec<complex>.

operator|, operator|=

Concatenation of two vectors.

operator<<

Prints vector on the standard output, or saves it to a file.

operator&

Elementwise multiplication of two vectors.

makefvec(string)

Returns a vector as specified by the string, e.g. makefvec(“1.2, 3.1”), or makefvec(“1:27”), as in MATLAB.

makcvec(fvec,fvec)

Makes a complex vector from two fvecs, representing the real and imaginary part.

energy(fvec), energy(cvec)

Computes the energy of the vector.

dot(fvec,fvec)

Dot (inner) product of two vectors.

fmat

fmat::fmat(), fmat::fmat(long,long)

Constructors.

fmat::load, fmat::save, fmat::loadascii, fmat::saveascii

Functions to load and save a matrix.

Math

(math2.h, elmat.h, random.h)

PI, TWOPI, ROOTPI, INVROOTPI, MAXFLOAT

Constants.

UniformRV, GaussRV, ExponentialRV, IuniformRV, IRV

Classes with random variables, several different distrubutions.

GaussRV::GaussRV(), GaussRV::GaussRV(float,float)

Constructors for the Gaussian random variable class. The first float argument is the mean, the second argument is the standard deviation. If no arguments are given, a N(0,1) random variable is created.

GaussRV::operator()

Returns a Gaussian random number, with mean and standard deviation as given in the constructor.

sin, cos, exp, log, log10, sqrt, pow

Standard mathematical functions, defined for variables of type float, double, complex, and vec<float>, vec<complex>.

abs, sign, round, trunc, fract, min, max, magnitude, phase, wrap, pow2, log2, sinc, sigmoid, conj, angle, imag, real

Additional mathematical functions. These functions work (in most cases) for variables of type float, double, complex, and vec<float>, vec<complex>.

randu(long), randn(long)

Returns uniform random numbers [0,1[ (randu) or Gaussian N(0,1) numbers (randn). If they are called without arguments, a single random number is returned. If they are called with a long argument, a vec<float> with random numbers is returned, with length determined by the argument.

erf, erfc, inverf, inverfc

The error function, the complementary error function, and their inverses.

cholesky(A,b), gausselim(A,b), roots(fvec)

cholesky and gausselim both solves the matrix equation Ax=b, and returns the vector x. roots finds the roots of a polynom.

integrate, fmins

Funtions for integration, and for finding the minimum of a function of several variables.

countones(long)

Counts the number of ones in the binary representation of the argument.

evenpoweroftwo(long)

Returns true if the argument is an even power of two.

Signal processing

(sigproc.h, fft.h, filter.h)

fft(fvec,long), fft(cvec,long), ifft(cvec,long), spectrum(fvec,long)

Computes the fft, the inverse fft, and the spectrum of a vec<float>. A second optional argument gives the desired length of the output vector.

hamming(long), hamming(fvec), do_hamming(fvec)

Hamming window.

harmonics(long,double), do_harmonics(cvec,double)

Returns cvec with harmonics.

lpc(fvec,long), levinson(fvec,long)

Functions for LPC analysis. lpc uses autocorr and levinson to compute the LPC filter coefficients.

conv(fvec,fvec), xcorr0(fvec,fvec), xcorr(fvec,fvec), autocorr(fvec,long)

Computes correlation functions.

mafilter, arfilter

Standard filter classes. mafilter is a moving average (FIR) filter, arfilter is an autoregressive (IIR) filter. If an ARMA filter is wanted, use an mafilter followed by an arfilter.

mafilter::mafilter(), arfilter::arfilter()

Constructors.

mafilter::setparams(fvec)

Set the filter parameters.

mafilter::operator()(float), mafilter::operator()(fvec)

Filters a float or a fvec, and returns the filtered float/fvec.

mavectorfilter, arvectorfilter

Vector filter classes.

Speech processing

(spcproc.h)

databasefile, databasefileset, databasespeech

Database classes.

a2k(fvec), k2a(fvec), a2lar(fvec), lar2a(fvec), a2lsf(fvec), lsf2a(fvec), a2cepstrum(fvec), cepstrum2a(fvec)

Functions for conversion between LPC parameters (a), reflection or PARCOR coefficients (k), log area ratios (lar), line spectrum frequencies (lsf) and cepstrum (cepstrum)

lpccovar(fvec,long), lpcschur(fvec,long), lerouxguegen(fvec,long)

Alternative (instead of  lpc with levinson) methods of LPC analysis.

chirp(fvec,float)

Chirps the vector.

sd(v1,v2), sd_cepstrum(v1,v2)

Computes the spectral distortion between two impulse response vectors. sd_cepstrum uses the cepstrum method, and is much faster.

Quantization

(sq.h, vq.h)

sq, vq, wvq, covq

Classes for scalar (sq) and vector (vq, wvq, covq) quantization. wvq (weighted vq) and covq (channel optimized vq) are derived from vq.

vq::vq(), vq::vq(string)

Constructors. The optional string argument gives the name of a codebook file, on ascii format.

vq::encode(fvec), vq::decode(lvec), vq::Q(fvec)

Functions for encoding, decoding and quantization (Q(x):=decode(encode(x));).

vq::setcodebook(fmat), vq::getcodebook()

Sets and gets the codebook from the VQ.

vq::size(), vq::dim()

Returns size and dimension of VQ.

vq::load(string), vq::save(string)

Loads and saves quantizers from/to ascii files.

MATLAB engine

(matlab.h, matfile.h)

matlabengine

An engine to execute MATLAB commands from C++.

matlabengine::matlabengine()

Constructor.

matlabengine::put(string, double/fvec/fmat)

Sends a variable to MATLAB, under the name given by the string argument.

matlabengine::get(string, double/fvec/fmat)

Recieves a variable from MATLAB.

matlabengine::plot(fvec), matlabengine::plot(fvec,fvec)

Plots directly in MATLAB.

matlabengine::exec(string)

Executes a MATLAB command, as specified by the argument

Examples

Basic functions and classes

tic();           // starts the timer

cout << toc() ;  // print the elapsed time since the last tic() call

errorif(2>1,”error”);// prints “error” on the screen (since 2 is indeed greater than 1)

 

timer T;         // defines a timer

T.start();       // starts the timer

T.stop();        // stops the timer;

cout << T.gettime();// print the elapsed time

T.reset();       // reset the timer

 

parser p(“setup.stp”);// defines a parser that handles setup files

parser p2(argc,argv);// defines a parser that reads command line arguments

string s=p.getstr(“FILENAME”);// gets the variable FILENAME from the setup file

long l=p.getint(“NUMDATA”);// gets an integer from the setup file

float f=p.getreal(“FACTOR”);//

 

bifstream file(“test”);// opens a binary input file

bofstream file2; // defines a binary output file, but does not open it

file2.open(“test2”);// opens the file

long x;

float f;

file >> x >> f ; // read data from the input file

files << f << x ;    // save data to the output file

 

string s;        // defines a string

s=”Hello, world!”;   // gives the string a value

cout << s << endl;   // prints Hello, world! on the screen

s=s.right(4);    // now s is “rld!”

 

Vectors

fvec x(10);      // defines a float vector with size 10. The elements are not inited.

cvec y;          // defines a complex vector with length 0.

x.clear();       // sets all element in vector to 0.

clear(x);

long L=length(x);    // gets length of x (number of elements).

long L=x.length();   // gets length of x (number of elements).

for (long i=0;i<length(x);i++) x[i]=randn();    // sets the elements to N(0,1) random numbers.

x=randn(10);     // sets the elements to N(0,1) random numbers

y=fft(x);        // computes the fft of x, and saves the rusult in the complex vector y.

cout<<y.left(length(y)/2); // prints the left part of y.

y.saveascii(“data.txt”); // saves y to the file data.txt

fvec z=2*x+abs(y);   // defines a new vector, and sets it to 2*x+abs(y).

float f=sum(z);  // sums all elements of z.

y=sort(x);       // sorts all elements of x in ascending order.

x.setlength(7); // sets length of x to 7. Copies the previous elements of x.

x.setlength(13);     // sets length to 13. The first 7 elements is copied, the rest is set to 0.

x=hamming(10);   // x is a Hamming window, length 10.

z=randu(10);     // z is a vector of 10 uniform distributed [0,1[ numbers.

z=z&x;   // z is set to the elementwise product of x and z. That is, z is Hamming windowed.

z=makefvec(“1.7,3.3,2.1”); // make a vector with elements as in the string.

y=sin(log(z));   // compute sinus of the logarithm of z.

Matrices

fmat A;          // defines a 0x0 matrix.

fmat B(10,10);   // defines a 10x10 matrix. The elements are not set to 0.

B.clear();       // sets all elements of B to 0.

for (long i=0;i<B.rows();i++) {      // fill B with random numbers 1..6

    for (long j=0;j<B.cols();j++) {

        B(i,j)=floor(6*randu()+1);

    }

}

A=t(inv(B));     // set A to the inverse transpose of B.

fvec x,b;       

b=randn(10);

x=inv(A)*b;      // solve the equation Ax=b

x=gausselim(A,b);    // solve the equation Ax=b

x=cholesky(A,b); // solve the equation Ax=b

cout << A << endl ;// print out A.

x=diag(A);       // get the diagonal elements of A.

float f=trace(A);    // the sum of the diagonal elements.

B=A*B+A;         // matrix math.

A=3*B-A;

cout << det(A);  // print the determinant of A.

A.save(“name.bin”);// save A on binary format.

A.saveascii(“name.txt”);// save A on ascii format.

A.loadascii(“name.txt”);// load A from ascii file.

MATH

GaussRV X;       // definition of a N(0,1) random variable

IUniformRV U(1,6);   // definition of a integer 1,2,...,6 random variable

float f=X();     // f is equal to a N(0,1) number

long L=U();      // L is random 1..6

 

long L;

float x,y;

cvec c;

fvec v=PI*ones(10);// v is a 10-dim vector with pi in all elements

x=max(x,y);      // max of x and y

x=pow2(y);       // x=y*y;

L=round(x);      // roundoff to closest integer. 0.5 is rounded up.

v=abs(c);        // absolute value

v=real(c);       // real part of complex vector

L=countones(2);  // count number of ones in binary representation of 2 (the answer is 1).

v=randu(10);     // v is a 10-dim vector with [0,1[ random numbers

Signal processing

cvec y;

fvec x,y,R,a;

y=fft(impulse(20));// computes the fft of an impulse, and returns to the complex vector y.

a=lpc(hamming(x),10); // 10th order LPC analysis of Hamming-windowed x.

R=autocorr(hamming(x),10);// same as above, with explicit calls of autocorr and levinson.

levinson(R,10);

R=conv(x,y);     // convolution of x and y.

R=xcorr(x,y);    // cross correlation of x and y;

float f=xcorr0(x,y);// cross correlation of x and y, computed only for delay 0.

 

arfilter  h1;    // AR filter.

h1.setparams(makefvec(“0.95 0.5 0.2”));

mafilter  h2;    // MA filter.

h2.setparams(hamming(20));

fvec x,y;        // filter a white sequence in h1 and h2.

x=randn(100);

y=h1(h2(x));

cout << h1.order() ;// print the order of h1.

Speech processing

fvec a,x;

x=randn(160);

a=lpc(x,10);     // 10th order LPC analysis.

a=chirp(a,0.99); // chirp (bandwidth expansion)

lsf=a2lsf(a);    // compute lsf (line spectrum frequencies)

lsf+=0.01*randn(length(lsf));// add a small noise to the lsf vector

cout << sd(a,lsf2a(lsf); // print the spectral distortion

Quantization

vq TestVQ;       // defines a vq

TestVQ.load(“CB”);   // loads a codebook to the VQ, from the ascii file CB.

long I;          // encodes a vector in the VQ.

fvec x,y;

x=randn(TestVQ.dim());

I=TestVQ.encode(x);

y=TestVQ.decode(I);// decodes the index I.

y=TestVQ(x);     // same as y=TestVQ.decode(TestVQ.encode(x));

cout << TestVQ.dim() << TestVQ.size() ; // prints the size and dimension of the VQ.

fmat M=TestVQ.getcodebook(); // gets the codebook to a matrix.

TestVQ.setcodebook(M); // sets the codebook.

MATLAB engine

matlabengine M;  // defines a MATLAB engine.

fvec x=impulse(100);// x is an impulse (a one followed by 99 zeroes).

M.put(“ximp”,x); // sends x to matlab, under the name ximp.

M.exe(“plot(ximp)”); // plots ximp in matlab.

M.plot(x);       // different way to do the same thing.

M.exe(“yresp=abs(fft(ximp));”);// computes the fft of ximp, using MATLAB.

fvec y=M.get(“yresp”);     // gets yresp to the vector y.

Full example (a very simple LPC-based speech coder)

 

#include <sp.h>

 

void main(int argc, char *argv[])

{

// get parameters from the setup file, or from command line

    parser       SetupFile(“setup.stp”,argc,argv);

    string       FILENAME;

    long         FRAMELENGTH;

 

    bifstream    SpeechFile;

    fvec         Speech,SynthesizedSpeech;

    fvec         Residual,Excitation;

    fvec         a,lsf;

    long         PitchPeriod,PulsePos;

    int          Voiced;

    float        Gain;

 

// Get setup parameters from setup file

    FILENAME=SetupFile.getstr(“FILENAME”);

    FRAMELENGTH=SetupFile.getint(“FRAMELENGTH”);

// Open the files and initiate variables

    SpeechInFile.open(FILENAME);

    SpeechOutFile.open(FILENAME+”q”); // add a “q” at the end of the filename.

    Speech.setlength(FRAMELENGTH);

    PulsePos=0;

// main loop until end of speechfile

    while (!SpeechFile.eof()) {

 

// THE ANALYSIS FIRST

 

// Read speech from a file

        SpeechFile >> Speech ;

// LPC analysis and quantization

        a=lpc(hamming(Speech),10); // 10th order LPC analysis, autocorrelation method

        a=chirp(a,0.99); // bandwidth expansion

        lsf=a2lsf(a);

        lsfindex=LSFQuantizer.encode(lsf);

// Get the LPC residual

        LPCFilter.setparams(a);

        Residual=LPCFilter(Speech);

// Compute the frame energy, and normalize the residual

        Gain=sqrt(energy(Residual));

        Residual=Residual/Gain;

// Find the pitch period (very simple method, dont use this in a real coder!)

        R=autocorr(Residual);

        PitchPeriod=maxindex(R); // find the period as the index with highest autocorrelation

// Voiced/unvoiced decision (very simple method, dont use this in a real coder!)

        if (R(PitchPeriod)/R(0)>0.4) {

            Voiced=true;

        } else {

            Voiced=false;

        }

 

// BELOW STARTS THE SYNTHESIS

 

// Synthesize voiced or unvoiced excitation

        if (Voiced) {

            Excitation=zeros(FRAMELENGTH); // excitation is a pulse train

            while (PulsePos<FRAMELENGTH) {

                Excitation[PulsePos]=1;

                PulsePos+=PitchPeriod;

            }

            PulsePos-=FRAMELENGTH; // prepare first pulse position for next frame

        } else {

            Excitation=randn(FRAMELENGTH); // excitation is white Gaussian noise

        }

// Set the frame energy

        Excitation/=sqrt(energy(Excitation)); // normalize to power 1

        Excitation*=Gain;

// Inverse filter the synthesized excitation, to get speech.

        lsf=LSFQuantizer.decode(lsfindex);

        InverseLPCFilter.setparams(lsf2a(lsf));

        SynthesizedSpeech=InverseLPCFilter(Excitation);

// Save in the output speech file

        SpeechOutFile << SynthesizedSpeech ;

    }

}

Frequently asked questions