diff --git a/libs/codec/gsm/COPYRIGHT b/libs/codec/gsm/COPYRIGHT new file mode 100644 index 0000000000..504978b134 --- /dev/null +++ b/libs/codec/gsm/COPYRIGHT @@ -0,0 +1,16 @@ +Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, +Technische Universitaet Berlin + +Any use of this software is permitted provided that this notice is not +removed and that neither the authors nor the Technische Universitaet Berlin +are deemed to have made any representations as to the suitability of this +software for any purpose nor are held responsible for any defects of +this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + +As a matter of courtesy, the authors request to be informed about uses +this software has found, about bugs in this software, and about any +improvements that may be of general interest. + +Berlin, 28.11.1994 +Jutta Degener +Carsten Bormann diff --git a/libs/codec/gsm/Makefile b/libs/codec/gsm/Makefile new file mode 100644 index 0000000000..46284640aa --- /dev/null +++ b/libs/codec/gsm/Makefile @@ -0,0 +1,583 @@ +# Copyright 1992-1996 by Jutta Degener and Carsten Bormann, Technische +# Universitaet Berlin. See the accompanying file "COPYRIGHT" for +# details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + +# Machine- or installation dependent flags you should configure to port + +SASR = -DSASR +######### Define SASR if >> is a signed arithmetic shift (-1 >> 1 == -1) + +#MULHACK = -DUSE_FLOAT_MUL +######### Define this if your host multiplies floats faster than integers, +######### e.g. on a SPARCstation. + +#FAST = -DFAST +######### Define together with USE_FLOAT_MUL to enable the GSM library's +######### approximation option for incorrect, but good-enough results. + +# LTP_CUT = -DLTP_CUT +LTP_CUT = +######### Define to enable the GSM library's long-term correlation +######### approximation option---faster, but worse; works for +######### both integer and floating point multiplications. +######### This flag is still in the experimental stage. + +WAV49 = -DWAV49 +#WAV49 = +######### Define to enable the GSM library's option to pack GSM frames +######### in the style used by the WAV #49 format. If you want to write +######### a tool that produces .WAV files which contain GSM-encoded data, +######### define this, and read about the GSM_OPT_WAV49 option in the +######### manual page on gsm_option(3). + +#K6OPT = -DK6OPT +#K6OPT = +######### Define to enable MMXTM optimizations for x86 architecture CPU's +######### which support MMX instructions. This should be newer pentiums, +######### ppro's, etc, as well as the AMD K6 and K7. The compile will +######### probably require gcc. + +ifneq (${OSARCH},Darwin) +ifneq (${OSARCH},SunOS) +ifneq (${PROC},x86_64) +ifneq (${PROC},ultrasparc) +ifneq ($(shell uname -m),ppc) +ifneq ($(shell uname -m),ppc64) +ifneq ($(shell uname -m),alpha) +ifneq ($(shell uname -m),armv4l) +ifneq (${PROC},sparc64) +ifneq (${PROC},arm) +ifneq (${PROC},ppc) +ifneq (${PROC},ppc64) +OPTIMIZE+=-march=$(PROC) +endif +endif +endif +endif +endif +endif +endif +endif +endif +endif +endif +endif + +#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only. +#This works for even old (2.96) versions of gcc and provides a small boost either way. +#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it. +#So we go lowest common available by gcc and go a step down, still a step up from +#the default as we now have a better instruction set to work with. - Belgarath +ifeq (${PROC},ultrasparc) +OPTIMIZE+=-mcpu=v8 -mtune=$(PROC) -O3 +endif + +PG = +#PG = -g -pg +######### Profiling flags. If you don't know what that means, leave it blank. + +# Choose a compiler. The code works both with ANSI and K&R-C. +# Use -DNeedFunctionPrototypes to compile with, -UNeedFunctionPrototypes to +# compile without, function prototypes in the header files. +# +# You can use the -DSTUPID_COMPILER to circumvent some compilers' +# static limits regarding the number of subexpressions in a statement. + +# CC = cc +# CCFLAGS = -c -DSTUPID_COMPILER + +# CC = /usr/lang/acc +# CCFLAGS = -c -O + +CC ?= gcc +CCFLAGS += -c -DNeedFunctionPrototypes=1 -funroll-loops $(OPTIMIZE) +ifneq ($(findstring CYGWIN,${OSARCH}),CYGWIN) +CCFLAGS += -fPIC +endif + + +LD = $(CC) + +# LD = gcc +# LDFLAGS = + + +# If your compiler needs additional flags/libraries, regardless of +# the source compiled, configure them here. + +# CCINC = -I/usr/gnu/lib/gcc-2.1/gcc-lib/sparc-sun-sunos4.1.2/2.1/include +######### Includes needed by $(CC) + +# LDINC = -L/usr/gnu/lib/gcc-2.1/gcc-lib/sparc-sun-sunos4.1.2/2.1 +######### Library paths needed by $(LD) + +# LDLIB = -lgcc +######### Additional libraries needed by $(LD) + + +# Where do you want to install libraries, binaries, a header file +# and the manual pages? +# +# Leave INSTALL_ROOT empty (or just don't execute "make install") to +# not install gsm and toast outside of this directory. + +INSTALL_ROOT = + +# Where do you want to install the gsm library, header file, and manpages? +# +# Leave GSM_INSTALL_ROOT empty to not install the GSM library outside of +# this directory. + +GSM_INSTALL_ROOT = $(INSTALL_ROOT) +GSM_INSTALL_LIB = $(GSM_INSTALL_ROOT)/lib +GSM_INSTALL_INC = $(GSM_INSTALL_ROOT)/inc +GSM_INSTALL_MAN = $(GSM_INSTALL_ROOT)/man/man3 + + +# Where do you want to install the toast binaries and their manpage? +# +# Leave TOAST_INSTALL_ROOT empty to not install the toast binaries outside +# of this directory. + +TOAST_INSTALL_ROOT = $(INSTALL_ROOT) +TOAST_INSTALL_BIN = $(TOAST_INSTALL_ROOT)/bin +TOAST_INSTALL_MAN = $(TOAST_INSTALL_ROOT)/man/man1 + +# Other tools + +SHELL = /bin/sh +LN = ln +BASENAME = basename +AR = ar +ARFLAGS = cr +RMFLAGS = -f +FIND = find +COMPRESS = compress +COMPRESSFLAGS = +# RANLIB = true +RANLIB = ranlib + +# +# You shouldn't have to configure below this line if you're porting. +# + + +# Local Directories + +ROOT = . +ADDTST = $(ROOT)/add-test +TST = $(ROOT)/tst +MAN = $(ROOT)/man +BIN = $(ROOT)/bin +SRC = $(ROOT)/src +LIB = $(ROOT)/lib +TLS = $(ROOT)/tls +INC = $(ROOT)/inc + +# Flags + +DEBUG = -DNDEBUG +######### Remove -DNDEBUG to enable assertions. + +CFLAGS += $(PG) $(CCFLAGS) $(SASR) $(DEBUG) $(MULHACK) $(FAST) \ + $(LTP_CUT) $(WAV49) $(K6OPT) $(CCINC) -I$(INC) +######### It's $(CC) $(CFLAGS) + +LFLAGS = $(PG) $(LDFLAGS) $(LDINC) +######### It's $(LD) $(LFLAGS) + + +# Targets + +LIBGSM = $(LIB)/libgsm.a +LIBGSMSO= $(LIB)/libgsm.so + +TOAST = $(BIN)/toast +UNTOAST = $(BIN)/untoast +TCAT = $(BIN)/tcat + +# Headers + +GSM_HEADERS = $(INC)/gsm.h + +HEADERS = $(INC)/proto.h \ + $(INC)/unproto.h \ + $(INC)/config.h \ + $(INC)/private.h \ + $(INC)/gsm.h \ + $(INC)/toast.h \ + $(TLS)/taste.h + +# Sources + +GSM_SOURCES = $(SRC)/add.c \ + $(SRC)/code.c \ + $(SRC)/debug.c \ + $(SRC)/decode.c \ + $(SRC)/long_term.c \ + $(SRC)/lpc.c \ + $(SRC)/preprocess.c \ + $(SRC)/rpe.c \ + $(SRC)/gsm_destroy.c \ + $(SRC)/gsm_decode.c \ + $(SRC)/gsm_encode.c \ + $(SRC)/gsm_explode.c \ + $(SRC)/gsm_implode.c \ + $(SRC)/gsm_create.c \ + $(SRC)/gsm_print.c \ + $(SRC)/gsm_option.c \ + $(SRC)/short_term.c \ + $(SRC)/table.c +ifeq (${OSARCH},Linux) +ifneq ($(shell uname -m),x86_64) +ifneq ($(shell uname -m),ppc) +ifneq ($(shell uname -m),ppc64) +ifneq ($(shell uname -m),alpha) +ifneq ($(shell uname -m),armv4l) +ifneq ($(shell uname -m),sparc64) +ifneq (${PROC},arm) +GSM_SOURCES+= $(SRC)/k6opt.s +endif +endif +endif +endif +endif +endif +endif +endif + +TOAST_SOURCES = $(SRC)/toast.c \ + $(SRC)/toast_lin.c \ + $(SRC)/toast_ulaw.c \ + $(SRC)/toast_alaw.c \ + $(SRC)/toast_audio.c + +SOURCES = $(GSM_SOURCES) \ + $(TOAST_SOURCES) \ + $(ADDTST)/add_test.c \ + $(TLS)/sour.c \ + $(TLS)/ginger.c \ + $(TLS)/sour1.dta \ + $(TLS)/sour2.dta \ + $(TLS)/bitter.c \ + $(TLS)/bitter.dta \ + $(TLS)/taste.c \ + $(TLS)/sweet.c \ + $(TST)/cod2lin.c \ + $(TST)/cod2txt.c \ + $(TST)/gsm2cod.c \ + $(TST)/lin2cod.c \ + $(TST)/lin2txt.c + +# Object files + +GSM_OBJECTS = $(SRC)/add.o \ + $(SRC)/code.o \ + $(SRC)/debug.o \ + $(SRC)/decode.o \ + $(SRC)/long_term.o \ + $(SRC)/lpc.o \ + $(SRC)/preprocess.o \ + $(SRC)/rpe.o \ + $(SRC)/gsm_destroy.o \ + $(SRC)/gsm_decode.o \ + $(SRC)/gsm_encode.o \ + $(SRC)/gsm_explode.o \ + $(SRC)/gsm_implode.o \ + $(SRC)/gsm_create.o \ + $(SRC)/gsm_print.o \ + $(SRC)/gsm_option.o \ + $(SRC)/short_term.o \ + $(SRC)/table.o + +ifeq (${OSARCH},Linux) +ifneq ($(shell uname -m), x86_64) +ifneq ($(shell uname -m), ppc) +ifneq ($(shell uname -m), ppc64) +ifneq ($(shell uname -m), alpha) +ifneq ($(shell uname -m), sparc64) +ifneq ($(shell uname -m), armv4l) +GSM_OBJECTS+= $(SRC)/k6opt.o +endif +endif +endif +endif +endif +endif +endif + +TOAST_OBJECTS = $(SRC)/toast.o \ + $(SRC)/toast_lin.o \ + $(SRC)/toast_ulaw.o \ + $(SRC)/toast_alaw.o \ + $(SRC)/toast_audio.o + +OBJECTS = $(GSM_OBJECTS) $(TOAST_OBJECTS) + +# Manuals + +GSM_MANUALS = $(MAN)/gsm.3 \ + $(MAN)/gsm_explode.3 \ + $(MAN)/gsm_option.3 \ + $(MAN)/gsm_print.3 + +TOAST_MANUALS = $(MAN)/toast.1 + +MANUALS = $(GSM_MANUALS) $(TOAST_MANUALS) $(MAN)/bitter.1 + +# Other stuff in the distribution + +STUFF = ChangeLog \ + INSTALL \ + MACHINES \ + MANIFEST \ + Makefile \ + README \ + $(ADDTST)/add_test.dta \ + $(TLS)/bitter.dta \ + $(TST)/run + + +# Install targets + +GSM_INSTALL_TARGETS = \ + $(GSM_INSTALL_LIB)/libgsm.a \ + $(GSM_INSTALL_INC)/gsm.h \ + $(GSM_INSTALL_MAN)/gsm.3 \ + $(GSM_INSTALL_MAN)/gsm_explode.3 \ + $(GSM_INSTALL_MAN)/gsm_option.3 \ + $(GSM_INSTALL_MAN)/gsm_print.3 + +TOAST_INSTALL_TARGETS = \ + $(TOAST_INSTALL_BIN)/toast \ + $(TOAST_INSTALL_BIN)/tcat \ + $(TOAST_INSTALL_BIN)/untoast \ + $(TOAST_INSTALL_MAN)/toast.1 + + +# Default rules + +.c.o: + $(CC) $(CFLAGS) $? + @-mv `$(BASENAME) $@` $@ > /dev/null 2>&1 + +# Target rules + +all: $(LIBGSM) $(LIBGSMSO) $(TOAST) $(TCAT) $(UNTOAST) + @-echo $(ROOT): Done. + +tst: $(TST)/lin2cod $(TST)/cod2lin $(TOAST) $(TST)/test-result + @-echo tst: Done. + +addtst: $(ADDTST)/add $(ADDTST)/add_test.dta + $(ADDTST)/add < $(ADDTST)/add_test.dta > /dev/null + @-echo addtst: Done. + +misc: $(TLS)/sweet $(TLS)/bitter $(TLS)/sour $(TLS)/ginger \ + $(TST)/lin2txt $(TST)/cod2txt $(TST)/gsm2cod + @-echo misc: Done. + +install: toastinstall gsminstall + @-echo install: Done. + + +# The basic API: libgsm + +$(LIBGSMSO): $(LIB) $(GSM_OBJECTS) + $(LD) -o $@.1.0.10 -shared -Xlinker -soname -Xlinker libgsm.so.1 $(GSM_OBJECTS) -lc + ln -fs libgsm.so.1.0.10 lib/libgsm.so.1 + ln -fs libgsm.so.1.0.10 lib/libgsm.so + +$(LIBGSM): $(LIB) $(GSM_OBJECTS) + -rm $(RMFLAGS) $(LIBGSM) + $(AR) $(ARFLAGS) $(LIBGSM) $(GSM_OBJECTS) + $(RANLIB) $(LIBGSM) + + +# Toast, Untoast and Tcat -- the compress-like frontends to gsm. + +$(TOAST): $(BIN) $(TOAST_OBJECTS) $(LIBGSM) + $(LD) $(LFLAGS) -o $(TOAST) $(TOAST_OBJECTS) $(LIBGSMSO) $(LDLIB) + +$(UNTOAST): $(BIN) $(TOAST) + -rm $(RMFLAGS) $(UNTOAST) + $(LN) toast $(UNTOAST) + +$(TCAT): $(BIN) $(TOAST) + -rm $(RMFLAGS) $(TCAT) + $(LN) toast $(TCAT) + + +# The local bin and lib directories + +$(BIN): + if [ ! -d $(BIN) ] ; then mkdir $(BIN) ; fi + +$(LIB): + if [ ! -d $(LIB) ] ; then mkdir $(LIB) ; fi + + +# Installation + +gsminstall: + -if [ x"$(GSM_INSTALL_ROOT)" != x ] ; then \ + $(MAKE) $(GSM_INSTALL_TARGETS) ; \ + fi + +toastinstall: + -if [ x"$(TOAST_INSTALL_ROOT)" != x ]; then \ + $(MAKE) $(TOAST_INSTALL_TARGETS); \ + fi + +gsmuninstall: + -if [ x"$(GSM_INSTALL_ROOT)" != x ] ; then \ + rm $(RMFLAGS) $(GSM_INSTALL_TARGETS) ; \ + fi + +toastuninstall: + -if [ x"$(TOAST_INSTALL_ROOT)" != x ] ; then \ + rm $(RMFLAGS) $(TOAST_INSTALL_TARGETS); \ + fi + +$(TOAST_INSTALL_BIN)/toast: $(TOAST) + -rm $@ + cp $(TOAST) $@ + chmod 755 $@ + +$(TOAST_INSTALL_BIN)/untoast: $(TOAST_INSTALL_BIN)/toast + -rm $@ + ln $? $@ + +$(TOAST_INSTALL_BIN)/tcat: $(TOAST_INSTALL_BIN)/toast + -rm $@ + ln $? $@ + +$(TOAST_INSTALL_MAN)/toast.1: $(MAN)/toast.1 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_MAN)/gsm.3: $(MAN)/gsm.3 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_MAN)/gsm_option.3: $(MAN)/gsm_option.3 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_MAN)/gsm_explode.3: $(MAN)/gsm_explode.3 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_MAN)/gsm_print.3: $(MAN)/gsm_print.3 + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_INC)/gsm.h: $(INC)/gsm.h + -rm $@ + cp $? $@ + chmod 444 $@ + +$(GSM_INSTALL_LIB)/libgsm.a: $(LIBGSM) + -rm $@ + cp $? $@ + chmod 444 $@ + + +# Distribution + +dist: gsm-1.0.tar.Z + @echo dist: Done. + +gsm-1.0.tar.Z: $(STUFF) $(SOURCES) $(HEADERS) $(MANUALS) + ( cd $(ROOT)/..; \ + tar cvf - `cat $(ROOT)/gsm-1.0/MANIFEST \ + | sed '/^#/d'` \ + ) | $(COMPRESS) $(COMPRESSFLAGS) > $(ROOT)/gsm-1.0.tar.Z + +# Clean + +uninstall: toastuninstall gsmuninstall + @-echo uninstall: Done. + +semi-clean: + -rm $(RMFLAGS) */*.o \ + $(TST)/lin2cod $(TST)/lin2txt \ + $(TST)/cod2lin $(TST)/cod2txt \ + $(TST)/gsm2cod \ + $(TST)/*.*.* + -$(FIND) . \( -name core -o -name foo \) \ + -print | xargs rm $(RMFLAGS) + +clean: semi-clean + -rm $(RMFLAGS) $(LIBGSM) $(ADDTST)/add \ + $(TOAST) $(TCAT) $(UNTOAST) \ + $(ROOT)/gsm-1.0.tar.Z + rm -rf lib + +# Two tools that helped me generate gsm_encode.c and gsm_decode.c, +# but aren't generally needed to port this. + +$(TLS)/sweet: $(TLS)/sweet.o $(TLS)/taste.o + $(LD) $(LFLAGS) -o $(TLS)/sweet \ + $(TLS)/sweet.o $(TLS)/taste.o $(LDLIB) + +$(TLS)/bitter: $(TLS)/bitter.o $(TLS)/taste.o + $(LD) $(LFLAGS) -o $(TLS)/bitter \ + $(TLS)/bitter.o $(TLS)/taste.o $(LDLIB) + +# A version of the same family that Jeff Chilton used to implement +# the WAV #49 GSM format. + +$(TLS)/ginger: $(TLS)/ginger.o $(TLS)/taste.o + $(LD) $(LFLAGS) -o $(TLS)/ginger \ + $(TLS)/ginger.o $(TLS)/taste.o $(LDLIB) + +$(TLS)/sour: $(TLS)/sour.o $(TLS)/taste.o + $(LD) $(LFLAGS) -o $(TLS)/sour \ + $(TLS)/sour.o $(TLS)/taste.o $(LDLIB) + +# Run $(ADDTST)/add < $(ADDTST)/add_test.dta to make sure the +# basic arithmetic functions work as intended. + +$(ADDTST)/add: $(ADDTST)/add_test.o + $(LD) $(LFLAGS) -o $(ADDTST)/add $(ADDTST)/add_test.o $(LDLIB) + + +# Various conversion programs between linear, text, .gsm and the code +# format used by the tests we ran (.cod). We paid for the test data, +# so I guess we can't just provide them with this package. Still, +# if you happen to have them lying around, here's the code. +# +# You can use gsm2cod | cod2txt independently to look at what's +# coded inside the compressed frames, although this shouldn't be +# hard to roll on your own using the gsm_print() function from +# the API. + + +$(TST)/test-result: $(TST)/lin2cod $(TST)/cod2lin $(TOAST) $(TST)/run + ( cd $(TST); ./run ) + +$(TST)/lin2txt: $(TST)/lin2txt.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/lin2txt \ + $(TST)/lin2txt.o $(LIBGSM) $(LDLIB) + +$(TST)/lin2cod: $(TST)/lin2cod.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/lin2cod \ + $(TST)/lin2cod.o $(LIBGSM) $(LDLIB) + +$(TST)/gsm2cod: $(TST)/gsm2cod.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/gsm2cod \ + $(TST)/gsm2cod.o $(LIBGSM) $(LDLIB) + +$(TST)/cod2txt: $(TST)/cod2txt.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/cod2txt \ + $(TST)/cod2txt.o $(LIBGSM) $(LDLIB) + +$(TST)/cod2lin: $(TST)/cod2lin.o $(LIBGSM) + $(LD) $(LFLAGS) -o $(TST)/cod2lin \ + $(TST)/cod2lin.o $(LIBGSM) $(LDLIB) diff --git a/libs/codec/gsm/README b/libs/codec/gsm/README new file mode 100644 index 0000000000..ebb1f16e44 --- /dev/null +++ b/libs/codec/gsm/README @@ -0,0 +1,37 @@ + +GSM 06.10 13 kbit/s RPE/LTP speech compression available +-------------------------------------------------------- + +The Communications and Operating Systems Research Group (KBS) at the +Technische Universitaet Berlin is currently working on a set of +UNIX-based tools for computer-mediated telecooperation that will be +made freely available. + +As part of this effort we are publishing an implementation of the +European GSM 06.10 provisional standard for full-rate speech +transcoding, prI-ETS 300 036, which uses RPE/LTP (residual pulse +excitation/long term prediction) coding at 13 kbit/s. + +GSM 06.10 compresses frames of 160 13-bit samples (8 kHz sampling +rate, i.e. a frame rate of 50 Hz) into 260 bits; for compatibility +with typical UNIX applications, our implementation turns frames of 160 +16-bit linear samples into 33-byte frames (1650 Bytes/s). +The quality of the algorithm is good enough for reliable speaker +recognition; even music often survives transcoding in recognizable +form (given the bandwidth limitations of 8 kHz sampling rate). + +The interfaces offered are a front end modelled after compress(1), and +a library API. Compression and decompression run faster than realtime +on most SPARCstations. The implementation has been verified against the +ETSI standard test patterns. + +Jutta Degener (jutta@cs.tu-berlin.de) +Carsten Bormann (cabo@cs.tu-berlin.de) + +Communications and Operating Systems Research Group, TU Berlin +Fax: +49.30.31425156, Phone: +49.30.31424315 + +-- +Copyright 1992 by Jutta Degener and Carsten Bormann, Technische +Universitaet Berlin. See the accompanying file "COPYRIGHT" for +details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. diff --git a/libs/codec/gsm/inc/config.h b/libs/codec/gsm/inc/config.h new file mode 100644 index 0000000000..07b21d17c0 --- /dev/null +++ b/libs/codec/gsm/inc/config.h @@ -0,0 +1,51 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#if 0 +efine SIGHANDLER_T int /* signal handlers are void */ +efine HAS_SYSV_SIGNAL 1 /* sigs not blocked/reset? */ +#endif + +#define HAS_STDLIB_H 1 /* /usr/include/stdlib.h */ +#if 0 +efine HAS_LIMITS_H 1 /* /usr/include/limits.h */ +#endif +#define HAS_FCNTL_H 1 /* /usr/include/fcntl.h */ +#if 0 +efine HAS_ERRNO_DECL 1 /* errno.h declares errno */ +#endif + +#define HAS_FSTAT 1 /* fstat syscall */ +#define HAS_FCHMOD 1 /* fchmod syscall */ +#define HAS_CHMOD 1 /* chmod syscall */ +#define HAS_FCHOWN 1 /* fchown syscall */ +#define HAS_CHOWN 1 /* chown syscall */ +#if 0 +efine HAS__FSETMODE 1 /* _fsetmode -- set file mode */ +#endif + +#define HAS_STRING_H 1 /* /usr/include/string.h */ +#if 0 +efine HAS_STRINGS_H 1 /* /usr/include/strings.h */ +#endif + +#define HAS_UNISTD_H 1 /* /usr/include/unistd.h */ +#define HAS_UTIME 1 /* POSIX utime(path, times) */ +#if 0 +efine HAS_UTIMES 1 /* use utimes() syscall instead */ +#endif +#define HAS_UTIME_H 1 /* UTIME header file */ +#if 0 +efine HAS_UTIMBUF 1 /* struct utimbuf */ +efine HAS_UTIMEUSEC 1 /* microseconds in utimbuf? */ +#endif + +#endif /* CONFIG_H */ diff --git a/libs/codec/gsm/inc/gsm.h b/libs/codec/gsm/inc/gsm.h new file mode 100644 index 0000000000..32a0b48279 --- /dev/null +++ b/libs/codec/gsm/inc/gsm.h @@ -0,0 +1,71 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef GSM_H +#define GSM_H + +#ifdef __cplusplus +# define NeedFunctionPrototypes 1 +#endif + +#if __STDC__ +# define NeedFunctionPrototypes 1 +#endif + +#ifdef _NO_PROTO +# undef NeedFunctionPrototypes +#endif + +#ifdef NeedFunctionPrototypes +# include /* for FILE * */ +#endif + +#undef GSM_P +#if NeedFunctionPrototypes +# define GSM_P( protos ) protos +#else +# define GSM_P( protos ) ( /* protos */ ) +#endif + +/* + * Interface + */ + +typedef struct gsm_state * gsm; +typedef short gsm_signal; /* signed 16 bit */ +typedef unsigned char gsm_byte; +typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */ + +#define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */ + +#define GSM_PATCHLEVEL 10 +#define GSM_MINOR 0 +#define GSM_MAJOR 1 + +#define GSM_OPT_VERBOSE 1 +#define GSM_OPT_FAST 2 +#define GSM_OPT_LTP_CUT 3 +#define GSM_OPT_WAV49 4 +#define GSM_OPT_FRAME_INDEX 5 +#define GSM_OPT_FRAME_CHAIN 6 + +extern gsm gsm_create GSM_P((void)); +extern void gsm_destroy GSM_P((gsm)); + +extern int gsm_print GSM_P((FILE *, gsm, gsm_byte *)); +extern int gsm_option GSM_P((gsm, int, int *)); + +extern void gsm_encode GSM_P((gsm, gsm_signal *, gsm_byte *)); +extern int gsm_decode GSM_P((gsm, gsm_byte *, gsm_signal *)); + +extern int gsm_explode GSM_P((gsm, gsm_byte *, gsm_signal *)); +extern void gsm_implode GSM_P((gsm, gsm_signal *, gsm_byte *)); + +#undef GSM_P + +#endif /* GSM_H */ diff --git a/libs/codec/gsm/inc/private.h b/libs/codec/gsm/inc/private.h new file mode 100644 index 0000000000..63a70a0434 --- /dev/null +++ b/libs/codec/gsm/inc/private.h @@ -0,0 +1,313 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef PRIVATE_H +#define PRIVATE_H + +typedef short word; /* 16 bit signed int */ +typedef long longword; /* 32 bit signed int */ + +typedef unsigned short uword; /* unsigned word */ +typedef unsigned long ulongword; /* unsigned longword */ + +struct gsm_state { + + word dp0[ 280 ]; + + word z1; /* preprocessing.c, Offset_com. */ + longword L_z2; /* Offset_com. */ + int mp; /* Preemphasis */ + + word u[8]; /* short_term_aly_filter.c */ + word LARpp[2][8]; /* */ + word j; /* */ + + word ltp_cut; /* long_term.c, LTP crosscorr. */ + word nrp; /* 40 */ /* long_term.c, synthesis */ + word v[9]; /* short_term.c, synthesis */ + word msr; /* decoder.c, Postprocessing */ + + char verbose; /* only used if !NDEBUG */ + char fast; /* only used if FAST */ + + char wav_fmt; /* only used if WAV49 defined */ + unsigned char frame_index; /* odd/even chaining */ + unsigned char frame_chain; /* half-byte to carry forward */ +}; + + +#define MIN_WORD (-32767 - 1) +#define MAX_WORD 32767 + +#define MIN_LONGWORD (-2147483647 - 1) +#define MAX_LONGWORD 2147483647 + +#ifdef SASR /* flag: >> is a signed arithmetic shift right */ +#undef SASR +#define SASR(x, by) ((x) >> (by)) +#else +#define SASR(x, by) ((x) >= 0 ? (x) >> (by) : (~(-((x) + 1) >> (by)))) +#endif /* SASR */ + +#include "proto.h" + +/* + * Prototypes from add.c + */ +extern word gsm_mult P((word a, word b)); +extern longword gsm_L_mult P((word a, word b)); +extern word gsm_mult_r P((word a, word b)); + +extern word gsm_div P((word num, word denum)); + +extern word gsm_add P(( word a, word b )); +extern longword gsm_L_add P(( longword a, longword b )); + +extern word gsm_sub P((word a, word b)); +extern longword gsm_L_sub P((longword a, longword b)); + +extern word gsm_abs P((word a)); + +extern word gsm_norm P(( longword a )); + +extern longword gsm_L_asl P((longword a, int n)); +extern word gsm_asl P((word a, int n)); + +extern longword gsm_L_asr P((longword a, int n)); +extern word gsm_asr P((word a, int n)); + +/* + * Inlined functions from add.h + */ + +/* + * #define GSM_MULT_R(a, b) (* word a, word b, !(a == b == MIN_WORD) *) \ + * (0x0FFFF & SASR(((longword)(a) * (longword)(b) + 16384), 15)) + */ +#define GSM_MULT_R(a, b) /* word a, word b, !(a == b == MIN_WORD) */ \ + (SASR( ((longword)(a) * (longword)(b) + 16384), 15 )) + +# define GSM_MULT(a,b) /* word a, word b, !(a == b == MIN_WORD) */ \ + (SASR( ((longword)(a) * (longword)(b)), 15 )) + +# define GSM_L_MULT(a, b) /* word a, word b */ \ + (((longword)(a) * (longword)(b)) << 1) + +#if defined(__GNUC__) && defined(__i386__) + +static __inline__ int GSM_L_ADD(int a, int b) +{ + __asm__ __volatile__( + + "addl %2,%0; jno 0f; movl $0x7fffffff,%0; adcl $0,%0; 0:" + : "=r" (a) + : "0" (a), "ir" (b) + : "cc" + ); + return(a); +} + +static __inline__ short GSM_ADD(short a, short b) +{ + __asm__ __volatile__( + "addw %2,%0; jno 0f; movw $0x7fff,%0; adcw $0,%0; 0:" + : "=r" (a) + : "0" (a), "ir" (b) + : "cc" + ); + return(a); +} + +static __inline__ short GSM_SUB(short a, short b) +{ + __asm__ __volatile__( + "subw %2,%0; jno 0f; movw $0x7fff,%0; adcw $0,%0; 0:" + : "=r" (a) + : "0" (a), "ir" (b) + : "cc" + ); + return(a); +} + +#else + +# define GSM_L_ADD(a, b) \ + ( (a) < 0 ? ( (b) >= 0 ? (a) + (b) \ + : (utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1)) \ + >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)utmp-2 ) \ + : ((b) <= 0 ? (a) + (b) \ + : (utmp = (ulongword)(a) + (ulongword)(b)) >= MAX_LONGWORD \ + ? MAX_LONGWORD : utmp)) + +/* + * # define GSM_ADD(a, b) \ + * ((ltmp = (longword)(a) + (longword)(b)) >= MAX_WORD \ + * ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) + */ +/* Nonportable, but faster: */ + +# define GSM_ADD(a, b) ({ \ + register longword ltmp; \ + ltmp = (longword) (a) + (longword) (b); \ + ((ulongword) (ltmp - MIN_WORD) > MAX_WORD - MIN_WORD ? \ + (ltmp > 0 ? MAX_WORD : MIN_WORD) : ltmp); \ + }) + +#define GSM_SUB(a, b) ({ \ + register longword ltmp; \ + ltmp = (longword) (a) - (longword) (b); \ + (ltmp >= MAX_WORD ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp); \ + }) + +#endif + +# define GSM_ABS(a) ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a)) + +/* Use these if necessary: + +# define GSM_MULT_R(a, b) gsm_mult_r(a, b) +# define GSM_MULT(a, b) gsm_mult(a, b) +# define GSM_L_MULT(a, b) gsm_L_mult(a, b) + +# define GSM_L_ADD(a, b) gsm_L_add(a, b) +# define GSM_ADD(a, b) gsm_add(a, b) +# define GSM_SUB(a, b) gsm_sub(a, b) + +# define GSM_ABS(a) gsm_abs(a) + +*/ + +/* + * More prototypes from implementations.. + */ +extern void Gsm_Coder P(( + struct gsm_state * S, + word * s, /* [0..159] samples IN */ + word * LARc, /* [0..7] LAR coefficients OUT */ + word * Nc, /* [0..3] LTP lag OUT */ + word * bc, /* [0..3] coded LTP gain OUT */ + word * Mc, /* [0..3] RPE grid selection OUT */ + word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ + word * xMc /* [13*4] normalized RPE samples OUT */)); + +extern void Gsm_Long_Term_Predictor P(( /* 4x for 160 samples */ + struct gsm_state * S, + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + word * e, /* [0..40] OUT */ + word * dpp, /* [0..40] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc /* gain factor OUT */)); + +extern void Gsm_LPC_Analysis P(( + struct gsm_state * S, + word * s, /* 0..159 signals IN/OUT */ + word * LARc)); /* 0..7 LARc's OUT */ + +extern void Gsm_Preprocess P(( + struct gsm_state * S, + word * s, word * so)); + +extern void Gsm_Encoding P(( + struct gsm_state * S, + word * e, + word * ep, + word * xmaxc, + word * Mc, + word * xMc)); + +extern void Gsm_Short_Term_Analysis_Filter P(( + struct gsm_state * S, + word * LARc, /* coded log area ratio [0..7] IN */ + word * d /* st res. signal [0..159] IN/OUT */)); + +extern void Gsm_Decoder P(( + struct gsm_state * S, + word * LARcr, /* [0..7] IN */ + word * Ncr, /* [0..3] IN */ + word * bcr, /* [0..3] IN */ + word * Mcr, /* [0..3] IN */ + word * xmaxcr, /* [0..3] IN */ + word * xMcr, /* [0..13*4] IN */ + word * s)); /* [0..159] OUT */ + +extern void Gsm_Decoding P(( + struct gsm_state * S, + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12] IN */ + word * erp)); /* [0..39] OUT */ + +extern void Gsm_Long_Term_Synthesis_Filtering P(( + struct gsm_state* S, + word Ncr, + word bcr, + word * erp, /* [0..39] IN */ + word * drp)); /* [-120..-1] IN, [0..40] OUT */ + +void Gsm_RPE_Decoding P(( + struct gsm_state *S, + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12], 3 bits IN */ + word * erp)); /* [0..39] OUT */ + +void Gsm_RPE_Encoding P(( + struct gsm_state * S, + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc)); /* [0..12] OUT */ + +extern void Gsm_Short_Term_Synthesis_Filter P(( + struct gsm_state * S, + word * LARcr, /* log area ratios [0..7] IN */ + word * drp, /* received d [0...39] IN */ + word * s)); /* signal s [0..159] OUT */ + +extern void Gsm_Update_of_reconstructed_short_time_residual_signal P(( + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp)); /* [-120...-1] IN/OUT */ + +/* + * Tables from table.c + */ +#ifndef GSM_TABLE_C + +extern word gsm_A[8], gsm_B[8], gsm_MIC[8], gsm_MAC[8]; +extern word gsm_INVA[8]; +extern word gsm_DLB[4], gsm_QLB[4]; +extern word gsm_H[11]; +extern word gsm_NRFAC[8]; +extern word gsm_FAC[8]; + +#endif /* GSM_TABLE_C */ + +/* + * Debugging + */ +#ifdef NDEBUG + +# define gsm_debug_words(a, b, c, d) /* nil */ +# define gsm_debug_longwords(a, b, c, d) /* nil */ +# define gsm_debug_word(a, b) /* nil */ +# define gsm_debug_longword(a, b) /* nil */ + +#else /* !NDEBUG => DEBUG */ + + extern void gsm_debug_words P((char * name, int, int, word *)); + extern void gsm_debug_longwords P((char * name, int, int, longword *)); + extern void gsm_debug_longword P((char * name, longword)); + extern void gsm_debug_word P((char * name, word)); + +#endif /* !NDEBUG */ + +#include "unproto.h" + +#endif /* PRIVATE_H */ diff --git a/libs/codec/gsm/inc/proto.h b/libs/codec/gsm/inc/proto.h new file mode 100644 index 0000000000..17a5f745b5 --- /dev/null +++ b/libs/codec/gsm/inc/proto.h @@ -0,0 +1,65 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifndef PROTO_H +#define PROTO_H + +#if __cplusplus +# define NeedFunctionPrototypes 1 +#endif + +#if __STDC__ +# define NeedFunctionPrototypes 1 +#endif + +#ifdef _NO_PROTO +# undef NeedFunctionPrototypes +#endif + +#undef P /* gnu stdio.h actually defines this... */ +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef P4 +#undef P5 +#undef P6 +#undef P7 +#undef P8 + +#if NeedFunctionPrototypes + +# define P( protos ) protos + +# define P0() (void) +# define P1(x, a) (a) +# define P2(x, a, b) (a, b) +# define P3(x, a, b, c) (a, b, c) +# define P4(x, a, b, c, d) (a, b, c, d) +# define P5(x, a, b, c, d, e) (a, b, c, d, e) +# define P6(x, a, b, c, d, e, f) (a, b, c, d, e, f) +# define P7(x, a, b, c, d, e, f, g) (a, b, c, d, e, f, g) +# define P8(x, a, b, c, d, e, f, g, h) (a, b, c, d, e, f, g, h) + +#else /* !NeedFunctionPrototypes */ + +# define P( protos ) ( /* protos */ ) + +# define P0() () +# define P1(x, a) x a; +# define P2(x, a, b) x a; b; +# define P3(x, a, b, c) x a; b; c; +# define P4(x, a, b, c, d) x a; b; c; d; +# define P5(x, a, b, c, d, e) x a; b; c; d; e; +# define P6(x, a, b, c, d, e, f) x a; b; c; d; e; f; +# define P7(x, a, b, c, d, e, f, g) x a; b; c; d; e; f; g; +# define P8(x, a, b, c, d, e, f, g, h) x a; b; c; d; e; f; g; h; + +#endif /* !NeedFunctionPrototypes */ + +#endif /* PROTO_H */ diff --git a/libs/codec/gsm/inc/unproto.h b/libs/codec/gsm/inc/unproto.h new file mode 100644 index 0000000000..ce09e1a80f --- /dev/null +++ b/libs/codec/gsm/inc/unproto.h @@ -0,0 +1,23 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/*$Header$*/ + +#ifdef PROTO_H /* sic */ +#undef PROTO_H + +#undef P +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef P4 +#undef P5 +#undef P6 +#undef P7 +#undef P8 + +#endif /* PROTO_H */ diff --git a/libs/codec/gsm/src/add.c b/libs/codec/gsm/src/add.c new file mode 100644 index 0000000000..9c5171e6fb --- /dev/null +++ b/libs/codec/gsm/src/add.c @@ -0,0 +1,235 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +/* + * See private.h for the more commonly used macro versions. + */ + +#include +#include + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +#define saturate(x) \ + ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) + +word gsm_add P2((a,b), word a, word b) +{ + longword sum = (longword)a + (longword)b; + return saturate(sum); +} + +word gsm_sub P2((a,b), word a, word b) +{ + longword diff = (longword)a - (longword)b; + return saturate(diff); +} + +word gsm_mult P2((a,b), word a, word b) +{ + if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; + else return SASR( (longword)a * (longword)b, 15 ); +} + +word gsm_mult_r P2((a,b), word a, word b) +{ + if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; + else { + longword prod = (longword)a * (longword)b + 16384; + prod >>= 15; + return prod & 0xFFFF; + } +} + +word gsm_abs P1((a), word a) +{ + return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; +} + +longword gsm_L_mult P2((a,b),word a, word b) +{ + assert( a != MIN_WORD || b != MIN_WORD ); + return ((longword)a * (longword)b) << 1; +} + +longword gsm_L_add P2((a,b), longword a, longword b) +{ + if (a < 0) { + if (b >= 0) return a + b; + else { + ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); + return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; + } + } + else if (b <= 0) return a + b; + else { + ulongword A = (ulongword)a + (ulongword)b; + return A > MAX_LONGWORD ? MAX_LONGWORD : A; + } +} + +longword gsm_L_sub P2((a,b), longword a, longword b) +{ + if (a >= 0) { + if (b >= 0) return a - b; + else { + /* a>=0, b<0 */ + + ulongword A = (ulongword)a + -(b + 1); + return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); + } + } + else if (b <= 0) return a - b; + else { + /* a<0, b>0 */ + + ulongword A = (ulongword)-(a + 1) + b; + return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; + } +} + +static unsigned char const bitoff[ 256 ] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +word gsm_norm P1((a), longword a ) +/* + * the number of left shifts needed to normalize the 32 bit + * variable L_var1 for positive values on the interval + * + * with minimum of + * minimum of 1073741824 (01000000000000000000000000000000) and + * maximum of 2147483647 (01111111111111111111111111111111) + * + * + * and for negative values on the interval with + * minimum of -2147483648 (-10000000000000000000000000000000) and + * maximum of -1073741824 ( -1000000000000000000000000000000). + * + * in order to normalize the result, the following + * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); + * + * (That's 'ffs', only from the left, not the right..) + */ +{ + assert(a != 0); + + if (a < 0) { + if (a <= -1073741824) return 0; + a = ~a; + } + + return a & 0xffff0000 + ? ( a & 0xff000000 + ? -1 + bitoff[ 0xFF & (a >> 24) ] + : 7 + bitoff[ 0xFF & (a >> 16) ] ) + : ( a & 0xff00 + ? 15 + bitoff[ 0xFF & (a >> 8) ] + : 23 + bitoff[ 0xFF & a ] ); +} + +longword gsm_L_asl P2((a,n), longword a, int n) +{ + if (n >= 32) return 0; + if (n <= -32) return -(a < 0); + if (n < 0) return gsm_L_asr(a, -n); + return a << n; +} + +word gsm_asl P2((a,n), word a, int n) +{ + if (n >= 16) return 0; + if (n <= -16) return -(a < 0); + if (n < 0) return gsm_asr(a, -n); + return a << n; +} + +longword gsm_L_asr P2((a,n), longword a, int n) +{ + if (n >= 32) return -(a < 0); + if (n <= -32) return 0; + if (n < 0) return a << -n; + +# ifdef SASR + return a >> n; +# else + if (a >= 0) return a >> n; + else return -(longword)( -(ulongword)a >> n ); +# endif +} + +word gsm_asr P2((a,n), word a, int n) +{ + if (n >= 16) return -(a < 0); + if (n <= -16) return 0; + if (n < 0) return a << -n; + +# ifdef SASR + return a >> n; +# else + if (a >= 0) return a >> n; + else return -(word)( -(uword)a >> n ); +# endif +} + +/* + * (From p. 46, end of section 4.2.5) + * + * NOTE: The following lines gives [sic] one correct implementation + * of the div(num, denum) arithmetic operation. Compute div + * which is the integer division of num by denum: with denum + * >= num > 0 + */ + +word gsm_div P2((num,denum), word num, word denum) +{ + longword L_num = num; + longword L_denum = denum; + word div = 0; + int k = 15; + + /* The parameter num sometimes becomes zero. + * Although this is explicitly guarded against in 4.2.5, + * we assume that the result should then be zero as well. + */ + + /* assert(num != 0); */ + + assert(num >= 0 && denum >= num); + if (num == 0) + return 0; + + while (k--) { + div <<= 1; + L_num <<= 1; + + if (L_num >= L_denum) { + L_num -= L_denum; + div++; + } + } + + return div; +} diff --git a/libs/codec/gsm/src/code.c b/libs/codec/gsm/src/code.c new file mode 100644 index 0000000000..14c5f6c37b --- /dev/null +++ b/libs/codec/gsm/src/code.c @@ -0,0 +1,101 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "config.h" + +#ifdef HAS_STRING_H +#include +#else +# include "proto.h" + extern char * memcpy P((char *, char *, int)); +#endif + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +/* + * 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER + */ + +void Gsm_Coder P8((S,s,LARc,Nc,bc,Mc,xmaxc,xMc), + + struct gsm_state * S, + + word * s, /* [0..159] samples IN */ + +/* + * The RPE-LTD coder works on a frame by frame basis. The length of + * the frame is equal to 160 samples. Some computations are done + * once per frame to produce at the output of the coder the + * LARc[1..8] parameters which are the coded LAR coefficients and + * also to realize the inverse filtering operation for the entire + * frame (160 samples of signal d[0..159]). These parts produce at + * the output of the coder: + */ + + word * LARc, /* [0..7] LAR coefficients OUT */ + +/* + * Procedure 4.2.11 to 4.2.18 are to be executed four times per + * frame. That means once for each sub-segment RPE-LTP analysis of + * 40 samples. These parts produce at the output of the coder: + */ + + word * Nc, /* [0..3] LTP lag OUT */ + word * bc, /* [0..3] coded LTP gain OUT */ + word * Mc, /* [0..3] RPE grid selection OUT */ + word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ + word * xMc /* [13*4] normalized RPE samples OUT */ +) +{ + int k; + word * dp = S->dp0 + 120; /* [ -120...-1 ] */ + word * dpp = dp; /* [ 0...39 ] */ + + static word e[50]; + + word so[160]; + +#if !(defined(__GNUC__) && defined(__i386__)) + longword ltmp; +#endif + + Gsm_Preprocess (S, s, so); + Gsm_LPC_Analysis (S, so, LARc); + Gsm_Short_Term_Analysis_Filter (S, LARc, so); + + for (k = 0; k <= 3; k++, xMc += 13) { + + Gsm_Long_Term_Predictor ( S, + so+k*40, /* d [0..39] IN */ + dp, /* dp [-120..-1] IN */ + e + 5, /* e [0..39] OUT */ + dpp, /* dpp [0..39] OUT */ + Nc++, + bc++); + + Gsm_RPE_Encoding ( S, + e + 5, /* e ][0..39][ IN/OUT */ + xmaxc++, Mc++, xMc ); + /* + * Gsm_Update_of_reconstructed_short_time_residual_signal + * ( dpp, e + 5, dp ); + */ + + { register int i; + for (i = 0; i <= 39; i++) + dp[ i ] = GSM_ADD( e[5 + i], dpp[i] ); + } + dp += 40; + dpp += 40; + + } + (void)memcpy( (char *)S->dp0, (char *)(S->dp0 + 160), + 120 * sizeof(*S->dp0) ); +} diff --git a/libs/codec/gsm/src/debug.c b/libs/codec/gsm/src/debug.c new file mode 100644 index 0000000000..031a7f895b --- /dev/null +++ b/libs/codec/gsm/src/debug.c @@ -0,0 +1,76 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#ifndef NDEBUG + +/* If NDEBUG _is_ defined and no debugging should be performed, + * calls to functions in this module are #defined to nothing + * in private.h. + */ + +#include +#include "proto.h" + +void gsm_debug_words P4( (name, from, to, ptr), + char * name, + int from, + int to, + word * ptr) +{ + int nprinted = 0; + + fprintf( stderr, "%s [%d .. %d]: ", name, from, to ); + while (from <= to) { + fprintf(stderr, "%d ", ptr[ from ] ); + from++; + if (nprinted++ >= 7) { + nprinted = 0; + if (from < to) putc('\n', stderr); + } + } + putc('\n', stderr); +} + +void gsm_debug_longwords P4( (name, from, to, ptr), + char * name, + int from, + int to, + longword * ptr) +{ + int nprinted = 0; + + fprintf( stderr, "%s [%d .. %d]: ", name, from, to ); + while (from <= to) { + + fprintf(stderr, "%d ", ptr[ from ] ); + from++; + if (nprinted++ >= 7) { + nprinted = 0; + if (from < to) putc('\n', stderr); + } + } + putc('\n', stderr); +} + +void gsm_debug_longword P2( (name, value), + char * name, + longword value ) +{ + fprintf(stderr, "%s: %d\n", name, (long)value ); +} + +void gsm_debug_word P2( (name, value), + char * name, + word value ) +{ + fprintf(stderr, "%s: %d\n", name, (long)value); +} + +#endif diff --git a/libs/codec/gsm/src/decode.c b/libs/codec/gsm/src/decode.c new file mode 100644 index 0000000000..7039b5bb75 --- /dev/null +++ b/libs/codec/gsm/src/decode.c @@ -0,0 +1,62 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +/* + * 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER + */ + +static void Postprocessing P2((S,s), + struct gsm_state * S, + register word * s) +{ + register int k; + register word msr = S->msr; + register word tmp; + + for (k = 160; k--; s++) { + tmp = GSM_MULT_R( msr, 28180 ); + msr = GSM_ADD(*s, tmp); /* Deemphasis */ + *s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */ + } + S->msr = msr; +} + +void Gsm_Decoder P8((S,LARcr, Ncr,bcr,Mcr,xmaxcr,xMcr,s), + struct gsm_state * S, + + word * LARcr, /* [0..7] IN */ + + word * Ncr, /* [0..3] IN */ + word * bcr, /* [0..3] IN */ + word * Mcr, /* [0..3] IN */ + word * xmaxcr, /* [0..3] IN */ + word * xMcr, /* [0..13*4] IN */ + + word * s) /* [0..159] OUT */ +{ + int j, k; + word erp[40], wt[160]; + word * drp = S->dp0 + 120; + + for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) { + + Gsm_RPE_Decoding( S, *xmaxcr, *Mcr, xMcr, erp ); + Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp ); + + for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ]; + } + + Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s ); + Postprocessing(S, s); +} diff --git a/libs/codec/gsm/src/gsm_create.c b/libs/codec/gsm/src/gsm_create.c new file mode 100644 index 0000000000..884549ea3f --- /dev/null +++ b/libs/codec/gsm/src/gsm_create.c @@ -0,0 +1,45 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +static char const ident[] = "$Header$"; + +#include "config.h" + +#ifdef HAS_STRING_H +#include +#else +# include "proto.h" + extern char * memset P((char *, int, int)); +#endif + +#ifdef HAS_STDLIB_H +# include +#else +# ifdef HAS_MALLOC_H +# include +# else + extern char * malloc(); +# endif +#endif + +#include + +#include "gsm.h" +#include "private.h" +#include "proto.h" + +gsm gsm_create P0() +{ + gsm r; + + r = (gsm)malloc(sizeof(struct gsm_state)); + if (!r) return r; + + memset((char *)r, 0, sizeof(*r)); + r->nrp = 40; + + return r; +} diff --git a/libs/codec/gsm/src/gsm_decode.c b/libs/codec/gsm/src/gsm_decode.c new file mode 100644 index 0000000000..0fa6d3e1d7 --- /dev/null +++ b/libs/codec/gsm/src/gsm_decode.c @@ -0,0 +1,361 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_decode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + + s->frame_index = !s->frame_index; + if (s->frame_index) { + + sr = *c++; + LARc[0] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 2; + LARc[1] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 4; + LARc[2] = sr & 0x1f; sr >>= 5; + LARc[3] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 2; + LARc[4] = sr & 0xf; sr >>= 4; + LARc[5] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; /* 5 */ + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[0] = sr & 0x7f; sr >>= 7; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[0] = sr & 0x3f; sr >>= 6; + xmc[0] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[1] = sr & 0x7; sr >>= 3; + xmc[2] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + xmc[5] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 10 */ + xmc[6] = sr & 0x7; sr >>= 3; + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[9] = sr & 0x7; sr >>= 3; + xmc[10] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[1] = sr & 0x7f; sr >>= 7; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[1] = sr & 0x3f; sr >>= 6; + xmc[13] = sr & 0x7; sr >>= 3; + sr = *c++; /* 15 */ + xmc[14] = sr & 0x7; sr >>= 3; + xmc[15] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + xmc[18] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[19] = sr & 0x7; sr >>= 3; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[22] = sr & 0x7; sr >>= 3; + xmc[23] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; /* 20 */ + Nc[2] = sr & 0x7f; sr >>= 7; + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[2] = sr & 0x3f; sr >>= 6; + xmc[26] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[27] = sr & 0x7; sr >>= 3; + xmc[28] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + xmc[31] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[32] = sr & 0x7; sr >>= 3; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + sr = *c++; /* 25 */ + xmc[35] = sr & 0x7; sr >>= 3; + xmc[36] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[3] = sr & 0x7f; sr >>= 7; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[3] = sr & 0x3f; sr >>= 6; + xmc[39] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[40] = sr & 0x7; sr >>= 3; + xmc[41] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 30 */ + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + xmc[44] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[45] = sr & 0x7; sr >>= 3; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->frame_chain; + sr |= (uword)*c++ << 4; /* 1 */ + LARc[0] = sr & 0x3f; sr >>= 6; + LARc[1] = sr & 0x3f; sr >>= 6; + sr = *c++; + LARc[2] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 3; + LARc[3] = sr & 0x1f; sr >>= 5; + LARc[4] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; + LARc[5] = sr & 0xf; sr >>= 4; + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr = *c++; /* 5 */ + Nc[0] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[0] = sr & 0x3f; sr >>= 6; + xmc[0] = sr & 0x7; sr >>= 3; + xmc[1] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[2] = sr & 0x7; sr >>= 3; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[5] = sr & 0x7; sr >>= 3; + xmc[6] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 10 */ + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + xmc[9] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[10] = sr & 0x7; sr >>= 3; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[1] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[1] = sr & 0x3f; sr >>= 6; + xmc[13] = sr & 0x7; sr >>= 3; + xmc[14] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 15 */ + xmc[15] = sr & 0x7; sr >>= 3; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[18] = sr & 0x7; sr >>= 3; + xmc[19] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + xmc[22] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[23] = sr & 0x7; sr >>= 3; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[2] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; /* 20 */ + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[2] = sr & 0x3f; sr >>= 6; + xmc[26] = sr & 0x7; sr >>= 3; + xmc[27] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[28] = sr & 0x7; sr >>= 3; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[31] = sr & 0x7; sr >>= 3; + xmc[32] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + xmc[35] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 25 */ + xmc[36] = sr & 0x7; sr >>= 3; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[3] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[3] = sr & 0x3f; sr >>= 6; + xmc[39] = sr & 0x7; sr >>= 3; + xmc[40] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[41] = sr & 0x7; sr >>= 3; + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + sr = *c++; /* 30 */ + xmc[44] = sr & 0x7; sr >>= 3; + xmc[45] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + xmc[48] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[49] = sr & 0x7; sr >>= 3; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + } + } + else +#endif + { + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + LARc[0] = (*c++ & 0xF) << 2; /* 1 */ + LARc[0] |= (*c >> 6) & 0x3; + LARc[1] = *c++ & 0x3F; + LARc[2] = (*c >> 3) & 0x1F; + LARc[3] = (*c++ & 0x7) << 2; + LARc[3] |= (*c >> 6) & 0x3; + LARc[4] = (*c >> 2) & 0xF; + LARc[5] = (*c++ & 0x3) << 2; + LARc[5] |= (*c >> 6) & 0x3; + LARc[6] = (*c >> 3) & 0x7; + LARc[7] = *c++ & 0x7; + Nc[0] = (*c >> 1) & 0x7F; + bc[0] = (*c++ & 0x1) << 1; + bc[0] |= (*c >> 7) & 0x1; + Mc[0] = (*c >> 5) & 0x3; + xmaxc[0] = (*c++ & 0x1F) << 1; + xmaxc[0] |= (*c >> 7) & 0x1; + xmc[0] = (*c >> 4) & 0x7; + xmc[1] = (*c >> 1) & 0x7; + xmc[2] = (*c++ & 0x1) << 2; + xmc[2] |= (*c >> 6) & 0x3; + xmc[3] = (*c >> 3) & 0x7; + xmc[4] = *c++ & 0x7; + xmc[5] = (*c >> 5) & 0x7; + xmc[6] = (*c >> 2) & 0x7; + xmc[7] = (*c++ & 0x3) << 1; /* 10 */ + xmc[7] |= (*c >> 7) & 0x1; + xmc[8] = (*c >> 4) & 0x7; + xmc[9] = (*c >> 1) & 0x7; + xmc[10] = (*c++ & 0x1) << 2; + xmc[10] |= (*c >> 6) & 0x3; + xmc[11] = (*c >> 3) & 0x7; + xmc[12] = *c++ & 0x7; + Nc[1] = (*c >> 1) & 0x7F; + bc[1] = (*c++ & 0x1) << 1; + bc[1] |= (*c >> 7) & 0x1; + Mc[1] = (*c >> 5) & 0x3; + xmaxc[1] = (*c++ & 0x1F) << 1; + xmaxc[1] |= (*c >> 7) & 0x1; + xmc[13] = (*c >> 4) & 0x7; + xmc[14] = (*c >> 1) & 0x7; + xmc[15] = (*c++ & 0x1) << 2; + xmc[15] |= (*c >> 6) & 0x3; + xmc[16] = (*c >> 3) & 0x7; + xmc[17] = *c++ & 0x7; + xmc[18] = (*c >> 5) & 0x7; + xmc[19] = (*c >> 2) & 0x7; + xmc[20] = (*c++ & 0x3) << 1; + xmc[20] |= (*c >> 7) & 0x1; + xmc[21] = (*c >> 4) & 0x7; + xmc[22] = (*c >> 1) & 0x7; + xmc[23] = (*c++ & 0x1) << 2; + xmc[23] |= (*c >> 6) & 0x3; + xmc[24] = (*c >> 3) & 0x7; + xmc[25] = *c++ & 0x7; + Nc[2] = (*c >> 1) & 0x7F; + bc[2] = (*c++ & 0x1) << 1; /* 20 */ + bc[2] |= (*c >> 7) & 0x1; + Mc[2] = (*c >> 5) & 0x3; + xmaxc[2] = (*c++ & 0x1F) << 1; + xmaxc[2] |= (*c >> 7) & 0x1; + xmc[26] = (*c >> 4) & 0x7; + xmc[27] = (*c >> 1) & 0x7; + xmc[28] = (*c++ & 0x1) << 2; + xmc[28] |= (*c >> 6) & 0x3; + xmc[29] = (*c >> 3) & 0x7; + xmc[30] = *c++ & 0x7; + xmc[31] = (*c >> 5) & 0x7; + xmc[32] = (*c >> 2) & 0x7; + xmc[33] = (*c++ & 0x3) << 1; + xmc[33] |= (*c >> 7) & 0x1; + xmc[34] = (*c >> 4) & 0x7; + xmc[35] = (*c >> 1) & 0x7; + xmc[36] = (*c++ & 0x1) << 2; + xmc[36] |= (*c >> 6) & 0x3; + xmc[37] = (*c >> 3) & 0x7; + xmc[38] = *c++ & 0x7; + Nc[3] = (*c >> 1) & 0x7F; + bc[3] = (*c++ & 0x1) << 1; + bc[3] |= (*c >> 7) & 0x1; + Mc[3] = (*c >> 5) & 0x3; + xmaxc[3] = (*c++ & 0x1F) << 1; + xmaxc[3] |= (*c >> 7) & 0x1; + xmc[39] = (*c >> 4) & 0x7; + xmc[40] = (*c >> 1) & 0x7; + xmc[41] = (*c++ & 0x1) << 2; + xmc[41] |= (*c >> 6) & 0x3; + xmc[42] = (*c >> 3) & 0x7; + xmc[43] = *c++ & 0x7; /* 30 */ + xmc[44] = (*c >> 5) & 0x7; + xmc[45] = (*c >> 2) & 0x7; + xmc[46] = (*c++ & 0x3) << 1; + xmc[46] |= (*c >> 7) & 0x1; + xmc[47] = (*c >> 4) & 0x7; + xmc[48] = (*c >> 1) & 0x7; + xmc[49] = (*c++ & 0x1) << 2; + xmc[49] |= (*c >> 6) & 0x3; + xmc[50] = (*c >> 3) & 0x7; + xmc[51] = *c & 0x7; /* 33 */ + } + + Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target); + + return 0; +} diff --git a/libs/codec/gsm/src/gsm_destroy.c b/libs/codec/gsm/src/gsm_destroy.c new file mode 100644 index 0000000000..a92c00649f --- /dev/null +++ b/libs/codec/gsm/src/gsm_destroy.c @@ -0,0 +1,26 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "gsm.h" +#include "config.h" +#include "proto.h" + +#ifdef HAS_STDLIB_H +# include +#else +# ifdef HAS_MALLOC_H +# include +# else + extern void free(); +# endif +#endif + +void gsm_destroy P1((S), gsm S) +{ + if (S) free((char *)S); +} diff --git a/libs/codec/gsm/src/gsm_encode.c b/libs/codec/gsm/src/gsm_encode.c new file mode 100644 index 0000000000..4a2392edfc --- /dev/null +++ b/libs/codec/gsm/src/gsm_encode.c @@ -0,0 +1,451 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +void gsm_encode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc); + + + /* variable size + + GSM_MAGIC 4 + + LARc[0] 6 + LARc[1] 6 + LARc[2] 5 + LARc[3] 5 + LARc[4] 4 + LARc[5] 4 + LARc[6] 3 + LARc[7] 3 + + Nc[0] 7 + bc[0] 2 + Mc[0] 2 + xmaxc[0] 6 + xmc[0] 3 + xmc[1] 3 + xmc[2] 3 + xmc[3] 3 + xmc[4] 3 + xmc[5] 3 + xmc[6] 3 + xmc[7] 3 + xmc[8] 3 + xmc[9] 3 + xmc[10] 3 + xmc[11] 3 + xmc[12] 3 + + Nc[1] 7 + bc[1] 2 + Mc[1] 2 + xmaxc[1] 6 + xmc[13] 3 + xmc[14] 3 + xmc[15] 3 + xmc[16] 3 + xmc[17] 3 + xmc[18] 3 + xmc[19] 3 + xmc[20] 3 + xmc[21] 3 + xmc[22] 3 + xmc[23] 3 + xmc[24] 3 + xmc[25] 3 + + Nc[2] 7 + bc[2] 2 + Mc[2] 2 + xmaxc[2] 6 + xmc[26] 3 + xmc[27] 3 + xmc[28] 3 + xmc[29] 3 + xmc[30] 3 + xmc[31] 3 + xmc[32] 3 + xmc[33] 3 + xmc[34] 3 + xmc[35] 3 + xmc[36] 3 + xmc[37] 3 + xmc[38] 3 + + Nc[3] 7 + bc[3] 2 + Mc[3] 2 + xmaxc[3] 6 + xmc[39] 3 + xmc[40] 3 + xmc[41] 3 + xmc[42] 3 + xmc[43] 3 + xmc[44] 3 + xmc[45] 3 + xmc[46] 3 + xmc[47] 3 + xmc[48] 3 + xmc[49] 3 + xmc[50] 3 + xmc[51] 3 + */ + +#ifdef WAV49 + + if (s->wav_fmt) { + s->frame_index = !s->frame_index; + if (s->frame_index) { + + uword sr; + + sr = 0; + sr = sr >> 6 | LARc[0] << 10; + sr = sr >> 6 | LARc[1] << 10; + *c++ = sr >> 4; + sr = sr >> 5 | LARc[2] << 11; + *c++ = sr >> 7; + sr = sr >> 5 | LARc[3] << 11; + sr = sr >> 4 | LARc[4] << 12; + *c++ = sr >> 6; + sr = sr >> 4 | LARc[5] << 12; + sr = sr >> 3 | LARc[6] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | LARc[7] << 13; + sr = sr >> 7 | Nc[0] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[0] << 14; + sr = sr >> 2 | Mc[0] << 14; + sr = sr >> 6 | xmaxc[0] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[0] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[1] << 13; + sr = sr >> 3 | xmc[2] << 13; + sr = sr >> 3 | xmc[3] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[4] << 13; + sr = sr >> 3 | xmc[5] << 13; + sr = sr >> 3 | xmc[6] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[7] << 13; + sr = sr >> 3 | xmc[8] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[9] << 13; + sr = sr >> 3 | xmc[10] << 13; + sr = sr >> 3 | xmc[11] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[12] << 13; + sr = sr >> 7 | Nc[1] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[1] << 14; + sr = sr >> 2 | Mc[1] << 14; + sr = sr >> 6 | xmaxc[1] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[13] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[14] << 13; + sr = sr >> 3 | xmc[15] << 13; + sr = sr >> 3 | xmc[16] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[17] << 13; + sr = sr >> 3 | xmc[18] << 13; + sr = sr >> 3 | xmc[19] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[20] << 13; + sr = sr >> 3 | xmc[21] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[22] << 13; + sr = sr >> 3 | xmc[23] << 13; + sr = sr >> 3 | xmc[24] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[25] << 13; + sr = sr >> 7 | Nc[2] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[2] << 14; + sr = sr >> 2 | Mc[2] << 14; + sr = sr >> 6 | xmaxc[2] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[26] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[27] << 13; + sr = sr >> 3 | xmc[28] << 13; + sr = sr >> 3 | xmc[29] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[30] << 13; + sr = sr >> 3 | xmc[31] << 13; + sr = sr >> 3 | xmc[32] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[33] << 13; + sr = sr >> 3 | xmc[34] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[35] << 13; + sr = sr >> 3 | xmc[36] << 13; + sr = sr >> 3 | xmc[37] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[38] << 13; + sr = sr >> 7 | Nc[3] << 9; + *c++ = sr >> 5; + sr = sr >> 2 | bc[3] << 14; + sr = sr >> 2 | Mc[3] << 14; + sr = sr >> 6 | xmaxc[3] << 10; + *c++ = sr >> 3; + sr = sr >> 3 | xmc[39] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[40] << 13; + sr = sr >> 3 | xmc[41] << 13; + sr = sr >> 3 | xmc[42] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[43] << 13; + sr = sr >> 3 | xmc[44] << 13; + sr = sr >> 3 | xmc[45] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[46] << 13; + sr = sr >> 3 | xmc[47] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[48] << 13; + sr = sr >> 3 | xmc[49] << 13; + sr = sr >> 3 | xmc[50] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[51] << 13; + sr = sr >> 4; + *c = sr >> 8; + s->frame_chain = *c; + } + else { + uword sr; + + sr = 0; + sr = sr >> 4 | s->frame_chain << 12; + sr = sr >> 6 | LARc[0] << 10; + *c++ = sr >> 6; + sr = sr >> 6 | LARc[1] << 10; + *c++ = sr >> 8; + sr = sr >> 5 | LARc[2] << 11; + sr = sr >> 5 | LARc[3] << 11; + *c++ = sr >> 6; + sr = sr >> 4 | LARc[4] << 12; + sr = sr >> 4 | LARc[5] << 12; + *c++ = sr >> 6; + sr = sr >> 3 | LARc[6] << 13; + sr = sr >> 3 | LARc[7] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[0] << 9; + sr = sr >> 2 | bc[0] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[0] << 14; + sr = sr >> 6 | xmaxc[0] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[0] << 13; + sr = sr >> 3 | xmc[1] << 13; + sr = sr >> 3 | xmc[2] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[3] << 13; + sr = sr >> 3 | xmc[4] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[5] << 13; + sr = sr >> 3 | xmc[6] << 13; + sr = sr >> 3 | xmc[7] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[8] << 13; + sr = sr >> 3 | xmc[9] << 13; + sr = sr >> 3 | xmc[10] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[11] << 13; + sr = sr >> 3 | xmc[12] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[1] << 9; + sr = sr >> 2 | bc[1] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[1] << 14; + sr = sr >> 6 | xmaxc[1] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[13] << 13; + sr = sr >> 3 | xmc[14] << 13; + sr = sr >> 3 | xmc[15] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[16] << 13; + sr = sr >> 3 | xmc[17] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[18] << 13; + sr = sr >> 3 | xmc[19] << 13; + sr = sr >> 3 | xmc[20] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[21] << 13; + sr = sr >> 3 | xmc[22] << 13; + sr = sr >> 3 | xmc[23] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[24] << 13; + sr = sr >> 3 | xmc[25] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[2] << 9; + sr = sr >> 2 | bc[2] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[2] << 14; + sr = sr >> 6 | xmaxc[2] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[26] << 13; + sr = sr >> 3 | xmc[27] << 13; + sr = sr >> 3 | xmc[28] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[29] << 13; + sr = sr >> 3 | xmc[30] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[31] << 13; + sr = sr >> 3 | xmc[32] << 13; + sr = sr >> 3 | xmc[33] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[34] << 13; + sr = sr >> 3 | xmc[35] << 13; + sr = sr >> 3 | xmc[36] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[37] << 13; + sr = sr >> 3 | xmc[38] << 13; + *c++ = sr >> 8; + sr = sr >> 7 | Nc[3] << 9; + sr = sr >> 2 | bc[3] << 14; + *c++ = sr >> 7; + sr = sr >> 2 | Mc[3] << 14; + sr = sr >> 6 | xmaxc[3] << 10; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[39] << 13; + sr = sr >> 3 | xmc[40] << 13; + sr = sr >> 3 | xmc[41] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[42] << 13; + sr = sr >> 3 | xmc[43] << 13; + *c++ = sr >> 8; + sr = sr >> 3 | xmc[44] << 13; + sr = sr >> 3 | xmc[45] << 13; + sr = sr >> 3 | xmc[46] << 13; + *c++ = sr >> 7; + sr = sr >> 3 | xmc[47] << 13; + sr = sr >> 3 | xmc[48] << 13; + sr = sr >> 3 | xmc[49] << 13; + *c++ = sr >> 6; + sr = sr >> 3 | xmc[50] << 13; + sr = sr >> 3 | xmc[51] << 13; + *c++ = sr >> 8; + } + } + + else + +#endif /* WAV49 */ + { + + *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ + | ((LARc[0] >> 2) & 0xF); + *c++ = ((LARc[0] & 0x3) << 6) + | (LARc[1] & 0x3F); + *c++ = ((LARc[2] & 0x1F) << 3) + | ((LARc[3] >> 2) & 0x7); + *c++ = ((LARc[3] & 0x3) << 6) + | ((LARc[4] & 0xF) << 2) + | ((LARc[5] >> 2) & 0x3); + *c++ = ((LARc[5] & 0x3) << 6) + | ((LARc[6] & 0x7) << 3) + | (LARc[7] & 0x7); + *c++ = ((Nc[0] & 0x7F) << 1) + | ((bc[0] >> 1) & 0x1); + *c++ = ((bc[0] & 0x1) << 7) + | ((Mc[0] & 0x3) << 5) + | ((xmaxc[0] >> 1) & 0x1F); + *c++ = ((xmaxc[0] & 0x1) << 7) + | ((xmc[0] & 0x7) << 4) + | ((xmc[1] & 0x7) << 1) + | ((xmc[2] >> 2) & 0x1); + *c++ = ((xmc[2] & 0x3) << 6) + | ((xmc[3] & 0x7) << 3) + | (xmc[4] & 0x7); + *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ + | ((xmc[6] & 0x7) << 2) + | ((xmc[7] >> 1) & 0x3); + *c++ = ((xmc[7] & 0x1) << 7) + | ((xmc[8] & 0x7) << 4) + | ((xmc[9] & 0x7) << 1) + | ((xmc[10] >> 2) & 0x1); + *c++ = ((xmc[10] & 0x3) << 6) + | ((xmc[11] & 0x7) << 3) + | (xmc[12] & 0x7); + *c++ = ((Nc[1] & 0x7F) << 1) + | ((bc[1] >> 1) & 0x1); + *c++ = ((bc[1] & 0x1) << 7) + | ((Mc[1] & 0x3) << 5) + | ((xmaxc[1] >> 1) & 0x1F); + *c++ = ((xmaxc[1] & 0x1) << 7) + | ((xmc[13] & 0x7) << 4) + | ((xmc[14] & 0x7) << 1) + | ((xmc[15] >> 2) & 0x1); + *c++ = ((xmc[15] & 0x3) << 6) + | ((xmc[16] & 0x7) << 3) + | (xmc[17] & 0x7); + *c++ = ((xmc[18] & 0x7) << 5) + | ((xmc[19] & 0x7) << 2) + | ((xmc[20] >> 1) & 0x3); + *c++ = ((xmc[20] & 0x1) << 7) + | ((xmc[21] & 0x7) << 4) + | ((xmc[22] & 0x7) << 1) + | ((xmc[23] >> 2) & 0x1); + *c++ = ((xmc[23] & 0x3) << 6) + | ((xmc[24] & 0x7) << 3) + | (xmc[25] & 0x7); + *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ + | ((bc[2] >> 1) & 0x1); + *c++ = ((bc[2] & 0x1) << 7) + | ((Mc[2] & 0x3) << 5) + | ((xmaxc[2] >> 1) & 0x1F); + *c++ = ((xmaxc[2] & 0x1) << 7) + | ((xmc[26] & 0x7) << 4) + | ((xmc[27] & 0x7) << 1) + | ((xmc[28] >> 2) & 0x1); + *c++ = ((xmc[28] & 0x3) << 6) + | ((xmc[29] & 0x7) << 3) + | (xmc[30] & 0x7); + *c++ = ((xmc[31] & 0x7) << 5) + | ((xmc[32] & 0x7) << 2) + | ((xmc[33] >> 1) & 0x3); + *c++ = ((xmc[33] & 0x1) << 7) + | ((xmc[34] & 0x7) << 4) + | ((xmc[35] & 0x7) << 1) + | ((xmc[36] >> 2) & 0x1); + *c++ = ((xmc[36] & 0x3) << 6) + | ((xmc[37] & 0x7) << 3) + | (xmc[38] & 0x7); + *c++ = ((Nc[3] & 0x7F) << 1) + | ((bc[3] >> 1) & 0x1); + *c++ = ((bc[3] & 0x1) << 7) + | ((Mc[3] & 0x3) << 5) + | ((xmaxc[3] >> 1) & 0x1F); + *c++ = ((xmaxc[3] & 0x1) << 7) + | ((xmc[39] & 0x7) << 4) + | ((xmc[40] & 0x7) << 1) + | ((xmc[41] >> 2) & 0x1); + *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ + | ((xmc[42] & 0x7) << 3) + | (xmc[43] & 0x7); + *c++ = ((xmc[44] & 0x7) << 5) + | ((xmc[45] & 0x7) << 2) + | ((xmc[46] >> 1) & 0x3); + *c++ = ((xmc[46] & 0x1) << 7) + | ((xmc[47] & 0x7) << 4) + | ((xmc[48] & 0x7) << 1) + | ((xmc[49] >> 2) & 0x1); + *c++ = ((xmc[49] & 0x3) << 6) + | ((xmc[50] & 0x7) << 3) + | (xmc[51] & 0x7); + + } +} diff --git a/libs/codec/gsm/src/gsm_explode.c b/libs/codec/gsm/src/gsm_explode.c new file mode 100644 index 0000000000..9c831a723c --- /dev/null +++ b/libs/codec/gsm/src/gsm_explode.c @@ -0,0 +1,417 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" +#include "gsm.h" +#include "proto.h" + +int gsm_explode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target) +{ +# define LARc target +# define Nc *((gsm_signal (*) [17])(target + 8)) +# define bc *((gsm_signal (*) [17])(target + 9)) +# define Mc *((gsm_signal (*) [17])(target + 10)) +# define xmaxc *((gsm_signal (*) [17])(target + 11)) + + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + + if (s->frame_index == 1) { + + sr = *c++; + LARc[0] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 2; + LARc[1] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 4; + LARc[2] = sr & 0x1f; sr >>= 5; + LARc[3] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 2; + LARc[4] = sr & 0xf; sr >>= 4; + LARc[5] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; /* 5 */ + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[0] = sr & 0x7f; sr >>= 7; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[0] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 12) + xmc[0] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[1] = sr & 0x7; sr >>= 3; + xmc[2] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + xmc[5] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 10 */ + xmc[6] = sr & 0x7; sr >>= 3; + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[9] = sr & 0x7; sr >>= 3; + xmc[10] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[1] = sr & 0x7f; sr >>= 7; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[1] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 29 - 13) + + xmc[13] = sr & 0x7; sr >>= 3; + sr = *c++; /* 15 */ + xmc[14] = sr & 0x7; sr >>= 3; + xmc[15] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + xmc[18] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[19] = sr & 0x7; sr >>= 3; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[22] = sr & 0x7; sr >>= 3; + xmc[23] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; /* 20 */ + Nc[2] = sr & 0x7f; sr >>= 7; + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[2] = sr & 0x3f; sr >>= 6; + +#undef xmc +#define xmc (target + 46 - 26) + + xmc[26] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[27] = sr & 0x7; sr >>= 3; + xmc[28] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + xmc[31] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[32] = sr & 0x7; sr >>= 3; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + sr = *c++; /* 25 */ + xmc[35] = sr & 0x7; sr >>= 3; + xmc[36] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[3] = sr & 0x7f; sr >>= 7; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[3] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 63 - 39) + + xmc[39] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[40] = sr & 0x7; sr >>= 3; + xmc[41] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 30 */ + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + xmc[44] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[45] = sr & 0x7; sr >>= 3; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->frame_chain; + sr |= (uword)*c++ << 4; /* 1 */ + LARc[0] = sr & 0x3f; sr >>= 6; + LARc[1] = sr & 0x3f; sr >>= 6; + sr = *c++; + LARc[2] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 3; + LARc[3] = sr & 0x1f; sr >>= 5; + LARc[4] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; + LARc[5] = sr & 0xf; sr >>= 4; + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr = *c++; /* 5 */ + Nc[0] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[0] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 12) + xmc[0] = sr & 0x7; sr >>= 3; + xmc[1] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[2] = sr & 0x7; sr >>= 3; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[5] = sr & 0x7; sr >>= 3; + xmc[6] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 10 */ + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + xmc[9] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[10] = sr & 0x7; sr >>= 3; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[1] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[1] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 29 - 13) + + xmc[13] = sr & 0x7; sr >>= 3; + xmc[14] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 15 */ + xmc[15] = sr & 0x7; sr >>= 3; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[18] = sr & 0x7; sr >>= 3; + xmc[19] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + xmc[22] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[23] = sr & 0x7; sr >>= 3; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[2] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; /* 20 */ + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[2] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (target + 46 - 26) + xmc[26] = sr & 0x7; sr >>= 3; + xmc[27] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[28] = sr & 0x7; sr >>= 3; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[31] = sr & 0x7; sr >>= 3; + xmc[32] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + xmc[35] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 25 */ + xmc[36] = sr & 0x7; sr >>= 3; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[3] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[3] = sr & 0x3f; sr >>= 6; + +#undef xmc +#define xmc (target + 63 - 39) + + xmc[39] = sr & 0x7; sr >>= 3; + xmc[40] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[41] = sr & 0x7; sr >>= 3; + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + sr = *c++; /* 30 */ + xmc[44] = sr & 0x7; sr >>= 3; + xmc[45] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + xmc[48] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[49] = sr & 0x7; sr >>= 3; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + } + } + else +#endif + { + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + LARc[0] = (*c++ & 0xF) << 2; /* 1 */ + LARc[0] |= (*c >> 6) & 0x3; + LARc[1] = *c++ & 0x3F; + LARc[2] = (*c >> 3) & 0x1F; + LARc[3] = (*c++ & 0x7) << 2; + LARc[3] |= (*c >> 6) & 0x3; + LARc[4] = (*c >> 2) & 0xF; + LARc[5] = (*c++ & 0x3) << 2; + LARc[5] |= (*c >> 6) & 0x3; + LARc[6] = (*c >> 3) & 0x7; + LARc[7] = *c++ & 0x7; + + Nc[0] = (*c >> 1) & 0x7F; + + bc[0] = (*c++ & 0x1) << 1; + bc[0] |= (*c >> 7) & 0x1; + + Mc[0] = (*c >> 5) & 0x3; + + xmaxc[0] = (*c++ & 0x1F) << 1; + xmaxc[0] |= (*c >> 7) & 0x1; + +#undef xmc +#define xmc (target + 12) + + xmc[0] = (*c >> 4) & 0x7; + xmc[1] = (*c >> 1) & 0x7; + xmc[2] = (*c++ & 0x1) << 2; + xmc[2] |= (*c >> 6) & 0x3; + xmc[3] = (*c >> 3) & 0x7; + xmc[4] = *c++ & 0x7; + xmc[5] = (*c >> 5) & 0x7; + xmc[6] = (*c >> 2) & 0x7; + xmc[7] = (*c++ & 0x3) << 1; /* 10 */ + xmc[7] |= (*c >> 7) & 0x1; + xmc[8] = (*c >> 4) & 0x7; + xmc[9] = (*c >> 1) & 0x7; + xmc[10] = (*c++ & 0x1) << 2; + xmc[10] |= (*c >> 6) & 0x3; + xmc[11] = (*c >> 3) & 0x7; + xmc[12] = *c++ & 0x7; + + Nc[1] = (*c >> 1) & 0x7F; + + bc[1] = (*c++ & 0x1) << 1; + bc[1] |= (*c >> 7) & 0x1; + + Mc[1] = (*c >> 5) & 0x3; + + xmaxc[1] = (*c++ & 0x1F) << 1; + xmaxc[1] |= (*c >> 7) & 0x1; + +#undef xmc +#define xmc (target + 29 - 13) + + xmc[13] = (*c >> 4) & 0x7; + xmc[14] = (*c >> 1) & 0x7; + xmc[15] = (*c++ & 0x1) << 2; + xmc[15] |= (*c >> 6) & 0x3; + xmc[16] = (*c >> 3) & 0x7; + xmc[17] = *c++ & 0x7; + xmc[18] = (*c >> 5) & 0x7; + xmc[19] = (*c >> 2) & 0x7; + xmc[20] = (*c++ & 0x3) << 1; + xmc[20] |= (*c >> 7) & 0x1; + xmc[21] = (*c >> 4) & 0x7; + xmc[22] = (*c >> 1) & 0x7; + xmc[23] = (*c++ & 0x1) << 2; + xmc[23] |= (*c >> 6) & 0x3; + xmc[24] = (*c >> 3) & 0x7; + xmc[25] = *c++ & 0x7; + + Nc[2] = (*c >> 1) & 0x7F; + + bc[2] = (*c++ & 0x1) << 1; /* 20 */ + bc[2] |= (*c >> 7) & 0x1; + + Mc[2] = (*c >> 5) & 0x3; + + xmaxc[2] = (*c++ & 0x1F) << 1; + xmaxc[2] |= (*c >> 7) & 0x1; + +#undef xmc +#define xmc (target + 46 - 26) + + xmc[26] = (*c >> 4) & 0x7; + xmc[27] = (*c >> 1) & 0x7; + xmc[28] = (*c++ & 0x1) << 2; + xmc[28] |= (*c >> 6) & 0x3; + xmc[29] = (*c >> 3) & 0x7; + xmc[30] = *c++ & 0x7; + xmc[31] = (*c >> 5) & 0x7; + xmc[32] = (*c >> 2) & 0x7; + xmc[33] = (*c++ & 0x3) << 1; + xmc[33] |= (*c >> 7) & 0x1; + xmc[34] = (*c >> 4) & 0x7; + xmc[35] = (*c >> 1) & 0x7; + xmc[36] = (*c++ & 0x1) << 2; + xmc[36] |= (*c >> 6) & 0x3; + xmc[37] = (*c >> 3) & 0x7; + xmc[38] = *c++ & 0x7; + + Nc[3] = (*c >> 1) & 0x7F; + + bc[3] = (*c++ & 0x1) << 1; + bc[3] |= (*c >> 7) & 0x1; + + Mc[3] = (*c >> 5) & 0x3; + + xmaxc[3] = (*c++ & 0x1F) << 1; + xmaxc[3] |= (*c >> 7) & 0x1; + +#undef xmc +#define xmc (target + 63 - 39) + + xmc[39] = (*c >> 4) & 0x7; + xmc[40] = (*c >> 1) & 0x7; + xmc[41] = (*c++ & 0x1) << 2; + xmc[41] |= (*c >> 6) & 0x3; + xmc[42] = (*c >> 3) & 0x7; + xmc[43] = *c++ & 0x7; /* 30 */ + xmc[44] = (*c >> 5) & 0x7; + xmc[45] = (*c >> 2) & 0x7; + xmc[46] = (*c++ & 0x3) << 1; + xmc[46] |= (*c >> 7) & 0x1; + xmc[47] = (*c >> 4) & 0x7; + xmc[48] = (*c >> 1) & 0x7; + xmc[49] = (*c++ & 0x1) << 2; + xmc[49] |= (*c >> 6) & 0x3; + xmc[50] = (*c >> 3) & 0x7; + xmc[51] = *c & 0x7; /* 33 */ + } + + return 0; +} diff --git a/libs/codec/gsm/src/gsm_implode.c b/libs/codec/gsm/src/gsm_implode.c new file mode 100644 index 0000000000..171836d133 --- /dev/null +++ b/libs/codec/gsm/src/gsm_implode.c @@ -0,0 +1,515 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +void gsm_implode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c) +{ + /* variable size index + + GSM_MAGIC 4 - + + LARc[0] 6 0 + LARc[1] 6 1 + LARc[2] 5 2 + LARc[3] 5 3 + LARc[4] 4 4 + LARc[5] 4 5 + LARc[6] 3 6 + LARc[7] 3 7 + + Nc[0] 7 8 + bc[0] 2 9 + Mc[0] 2 10 + xmaxc[0] 6 11 + xmc[0] 3 12 + xmc[1] 3 13 + xmc[2] 3 14 + xmc[3] 3 15 + xmc[4] 3 16 + xmc[5] 3 17 + xmc[6] 3 18 + xmc[7] 3 19 + xmc[8] 3 20 + xmc[9] 3 21 + xmc[10] 3 22 + xmc[11] 3 23 + xmc[12] 3 24 + + Nc[1] 7 25 + bc[1] 2 26 + Mc[1] 2 27 + xmaxc[1] 6 28 + xmc[13] 3 29 + xmc[14] 3 30 + xmc[15] 3 31 + xmc[16] 3 32 + xmc[17] 3 33 + xmc[18] 3 34 + xmc[19] 3 35 + xmc[20] 3 36 + xmc[21] 3 37 + xmc[22] 3 38 + xmc[23] 3 39 + xmc[24] 3 40 + xmc[25] 3 41 + + Nc[2] 7 42 + bc[2] 2 43 + Mc[2] 2 44 + xmaxc[2] 6 45 + xmc[26] 3 46 + xmc[27] 3 47 + xmc[28] 3 48 + xmc[29] 3 49 + xmc[30] 3 50 + xmc[31] 3 51 + xmc[32] 3 52 + xmc[33] 3 53 + xmc[34] 3 54 + xmc[35] 3 55 + xmc[36] 3 56 + xmc[37] 3 57 + xmc[38] 3 58 + + Nc[3] 7 59 + bc[3] 2 60 + Mc[3] 2 61 + xmaxc[3] 6 62 + xmc[39] 3 63 + xmc[40] 3 64 + xmc[41] 3 65 + xmc[42] 3 66 + xmc[43] 3 67 + xmc[44] 3 68 + xmc[45] 3 69 + xmc[46] 3 70 + xmc[47] 3 71 + xmc[48] 3 72 + xmc[49] 3 73 + xmc[50] 3 74 + xmc[51] 3 75 + */ + + /* There are 76 parameters per frame. The first eight are + * unique. The remaining 68 are four identical subframes of + * 17 parameters each. gsm_implode converts from a representation + * of these parameters as values in one array of signed words + * to the "packed" version of a GSM frame. + */ + +# define LARc source +# define Nc *((gsm_signal (*) [17])(source + 8)) +# define bc *((gsm_signal (*) [17])(source + 9)) +# define Mc *((gsm_signal (*) [17])(source + 10)) +# define xmaxc *((gsm_signal (*) [17])(source + 11)) + +#ifdef WAV49 + if (s->wav_fmt) { + + uword sr = 0; + if (s->frame_index == 0) { + + sr = *c++; + LARc[0] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 2; + LARc[1] = sr & 0x3f; sr >>= 6; + sr |= (uword)*c++ << 4; + LARc[2] = sr & 0x1f; sr >>= 5; + LARc[3] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 2; + LARc[4] = sr & 0xf; sr >>= 4; + LARc[5] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; /* 5 */ + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[0] = sr & 0x7f; sr >>= 7; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[0] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 12) + xmc[0] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[1] = sr & 0x7; sr >>= 3; + xmc[2] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + xmc[5] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 10 */ + xmc[6] = sr & 0x7; sr >>= 3; + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[9] = sr & 0x7; sr >>= 3; + xmc[10] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[1] = sr & 0x7f; sr >>= 7; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[1] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 29 - 13) + xmc[13] = sr & 0x7; sr >>= 3; + sr = *c++; /* 15 */ + xmc[14] = sr & 0x7; sr >>= 3; + xmc[15] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + xmc[18] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[19] = sr & 0x7; sr >>= 3; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[22] = sr & 0x7; sr >>= 3; + xmc[23] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; /* 20 */ + Nc[2] = sr & 0x7f; sr >>= 7; + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[2] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 46 - 26) + xmc[26] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[27] = sr & 0x7; sr >>= 3; + xmc[28] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + xmc[31] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[32] = sr & 0x7; sr >>= 3; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + sr = *c++; /* 25 */ + xmc[35] = sr & 0x7; sr >>= 3; + xmc[36] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 4; + Nc[3] = sr & 0x7f; sr >>= 7; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 1; + xmaxc[3] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 63 - 39) + + xmc[39] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[40] = sr & 0x7; sr >>= 3; + xmc[41] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 30 */ + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + xmc[44] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[45] = sr & 0x7; sr >>= 3; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[48] = sr & 0x7; sr >>= 3; + xmc[49] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + + s->frame_chain = sr & 0xf; + } + else { + sr = s->frame_chain; + sr |= (uword)*c++ << 4; /* 1 */ + LARc[0] = sr & 0x3f; sr >>= 6; + LARc[1] = sr & 0x3f; sr >>= 6; + sr = *c++; + LARc[2] = sr & 0x1f; sr >>= 5; + sr |= (uword)*c++ << 3; + LARc[3] = sr & 0x1f; sr >>= 5; + LARc[4] = sr & 0xf; sr >>= 4; + sr |= (uword)*c++ << 2; + LARc[5] = sr & 0xf; sr >>= 4; + LARc[6] = sr & 0x7; sr >>= 3; + LARc[7] = sr & 0x7; sr >>= 3; + sr = *c++; /* 5 */ + Nc[0] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[0] = sr & 0x3; sr >>= 2; + Mc[0] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[0] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 12) + xmc[0] = sr & 0x7; sr >>= 3; + xmc[1] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[2] = sr & 0x7; sr >>= 3; + xmc[3] = sr & 0x7; sr >>= 3; + xmc[4] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[5] = sr & 0x7; sr >>= 3; + xmc[6] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; /* 10 */ + xmc[7] = sr & 0x7; sr >>= 3; + xmc[8] = sr & 0x7; sr >>= 3; + xmc[9] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[10] = sr & 0x7; sr >>= 3; + xmc[11] = sr & 0x7; sr >>= 3; + xmc[12] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[1] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[1] = sr & 0x3; sr >>= 2; + Mc[1] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[1] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 29 - 13) + xmc[13] = sr & 0x7; sr >>= 3; + xmc[14] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 15 */ + xmc[15] = sr & 0x7; sr >>= 3; + xmc[16] = sr & 0x7; sr >>= 3; + xmc[17] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[18] = sr & 0x7; sr >>= 3; + xmc[19] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[20] = sr & 0x7; sr >>= 3; + xmc[21] = sr & 0x7; sr >>= 3; + xmc[22] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[23] = sr & 0x7; sr >>= 3; + xmc[24] = sr & 0x7; sr >>= 3; + xmc[25] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[2] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; /* 20 */ + bc[2] = sr & 0x3; sr >>= 2; + Mc[2] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[2] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 46 - 26) + xmc[26] = sr & 0x7; sr >>= 3; + xmc[27] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[28] = sr & 0x7; sr >>= 3; + xmc[29] = sr & 0x7; sr >>= 3; + xmc[30] = sr & 0x7; sr >>= 3; + sr = *c++; + xmc[31] = sr & 0x7; sr >>= 3; + xmc[32] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[33] = sr & 0x7; sr >>= 3; + xmc[34] = sr & 0x7; sr >>= 3; + xmc[35] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; /* 25 */ + xmc[36] = sr & 0x7; sr >>= 3; + xmc[37] = sr & 0x7; sr >>= 3; + xmc[38] = sr & 0x7; sr >>= 3; + sr = *c++; + Nc[3] = sr & 0x7f; sr >>= 7; + sr |= (uword)*c++ << 1; + bc[3] = sr & 0x3; sr >>= 2; + Mc[3] = sr & 0x3; sr >>= 2; + sr |= (uword)*c++ << 5; + xmaxc[3] = sr & 0x3f; sr >>= 6; +#undef xmc +#define xmc (source + 63 - 39) + + xmc[39] = sr & 0x7; sr >>= 3; + xmc[40] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[41] = sr & 0x7; sr >>= 3; + xmc[42] = sr & 0x7; sr >>= 3; + xmc[43] = sr & 0x7; sr >>= 3; + sr = *c++; /* 30 */ + xmc[44] = sr & 0x7; sr >>= 3; + xmc[45] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 2; + xmc[46] = sr & 0x7; sr >>= 3; + xmc[47] = sr & 0x7; sr >>= 3; + xmc[48] = sr & 0x7; sr >>= 3; + sr |= (uword)*c++ << 1; + xmc[49] = sr & 0x7; sr >>= 3; + xmc[50] = sr & 0x7; sr >>= 3; + xmc[51] = sr & 0x7; sr >>= 3; + } + } + else +#endif + { + + *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ + | ((LARc[0] >> 2) & 0xF); + *c++ = ((LARc[0] & 0x3) << 6) + | (LARc[1] & 0x3F); + *c++ = ((LARc[2] & 0x1F) << 3) + | ((LARc[3] >> 2) & 0x7); + *c++ = ((LARc[3] & 0x3) << 6) + | ((LARc[4] & 0xF) << 2) + | ((LARc[5] >> 2) & 0x3); + *c++ = ((LARc[5] & 0x3) << 6) + | ((LARc[6] & 0x7) << 3) + | (LARc[7] & 0x7); + + + *c++ = ((Nc[0] & 0x7F) << 1) + + + | ((bc[0] >> 1) & 0x1); + *c++ = ((bc[0] & 0x1) << 7) + + + | ((Mc[0] & 0x3) << 5) + + | ((xmaxc[0] >> 1) & 0x1F); + *c++ = ((xmaxc[0] & 0x1) << 7) + +#undef xmc +#define xmc (source + 12) + + | ((xmc[0] & 0x7) << 4) + | ((xmc[1] & 0x7) << 1) + | ((xmc[2] >> 2) & 0x1); + *c++ = ((xmc[2] & 0x3) << 6) + | ((xmc[3] & 0x7) << 3) + | (xmc[4] & 0x7); + *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ + | ((xmc[6] & 0x7) << 2) + | ((xmc[7] >> 1) & 0x3); + *c++ = ((xmc[7] & 0x1) << 7) + | ((xmc[8] & 0x7) << 4) + | ((xmc[9] & 0x7) << 1) + | ((xmc[10] >> 2) & 0x1); + *c++ = ((xmc[10] & 0x3) << 6) + | ((xmc[11] & 0x7) << 3) + | (xmc[12] & 0x7); + + + *c++ = ((Nc[1] & 0x7F) << 1) + + + | ((bc[1] >> 1) & 0x1); + *c++ = ((bc[1] & 0x1) << 7) + + + | ((Mc[1] & 0x3) << 5) + + + | ((xmaxc[1] >> 1) & 0x1F); + *c++ = ((xmaxc[1] & 0x1) << 7) + +#undef xmc +#define xmc (source + 29 - 13) + + | ((xmc[13] & 0x7) << 4) + | ((xmc[14] & 0x7) << 1) + | ((xmc[15] >> 2) & 0x1); + *c++ = ((xmc[15] & 0x3) << 6) + | ((xmc[16] & 0x7) << 3) + | (xmc[17] & 0x7); + *c++ = ((xmc[18] & 0x7) << 5) + | ((xmc[19] & 0x7) << 2) + | ((xmc[20] >> 1) & 0x3); + *c++ = ((xmc[20] & 0x1) << 7) + | ((xmc[21] & 0x7) << 4) + | ((xmc[22] & 0x7) << 1) + | ((xmc[23] >> 2) & 0x1); + *c++ = ((xmc[23] & 0x3) << 6) + | ((xmc[24] & 0x7) << 3) + | (xmc[25] & 0x7); + + + *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ + + + | ((bc[2] >> 1) & 0x1); + *c++ = ((bc[2] & 0x1) << 7) + + + | ((Mc[2] & 0x3) << 5) + + + | ((xmaxc[2] >> 1) & 0x1F); + *c++ = ((xmaxc[2] & 0x1) << 7) + +#undef xmc +#define xmc (source + 46 - 26) + + | ((xmc[26] & 0x7) << 4) + | ((xmc[27] & 0x7) << 1) + | ((xmc[28] >> 2) & 0x1); + *c++ = ((xmc[28] & 0x3) << 6) + | ((xmc[29] & 0x7) << 3) + | (xmc[30] & 0x7); + *c++ = ((xmc[31] & 0x7) << 5) + | ((xmc[32] & 0x7) << 2) + | ((xmc[33] >> 1) & 0x3); + *c++ = ((xmc[33] & 0x1) << 7) + | ((xmc[34] & 0x7) << 4) + | ((xmc[35] & 0x7) << 1) + | ((xmc[36] >> 2) & 0x1); + *c++ = ((xmc[36] & 0x3) << 6) + | ((xmc[37] & 0x7) << 3) + | (xmc[38] & 0x7); + + + *c++ = ((Nc[3] & 0x7F) << 1) + + + | ((bc[3] >> 1) & 0x1); + *c++ = ((bc[3] & 0x1) << 7) + + + | ((Mc[3] & 0x3) << 5) + + + | ((xmaxc[3] >> 1) & 0x1F); + *c++ = ((xmaxc[3] & 0x1) << 7) + +#undef xmc +#define xmc (source + 63 - 39) + + | ((xmc[39] & 0x7) << 4) + | ((xmc[40] & 0x7) << 1) + | ((xmc[41] >> 2) & 0x1); + *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ + | ((xmc[42] & 0x7) << 3) + | (xmc[43] & 0x7); + *c++ = ((xmc[44] & 0x7) << 5) + | ((xmc[45] & 0x7) << 2) + | ((xmc[46] >> 1) & 0x3); + *c++ = ((xmc[46] & 0x1) << 7) + | ((xmc[47] & 0x7) << 4) + | ((xmc[48] & 0x7) << 1) + | ((xmc[49] >> 2) & 0x1); + *c++ = ((xmc[49] & 0x3) << 6) + | ((xmc[50] & 0x7) << 3) + | (xmc[51] & 0x7); + } +} diff --git a/libs/codec/gsm/src/gsm_option.c b/libs/codec/gsm/src/gsm_option.c new file mode 100644 index 0000000000..7f33278803 --- /dev/null +++ b/libs/codec/gsm/src/gsm_option.c @@ -0,0 +1,69 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_option P3((r, opt, val), gsm r, int opt, int * val) +{ + int result = -1; + + switch (opt) { + case GSM_OPT_LTP_CUT: +#ifdef LTP_CUT + result = r->ltp_cut; + if (val) r->ltp_cut = *val; +#endif + break; + + case GSM_OPT_VERBOSE: +#ifndef NDEBUG + result = r->verbose; + if (val) r->verbose = *val; +#endif + break; + + case GSM_OPT_FAST: + +#if defined(FAST) && defined(USE_FLOAT_MUL) + result = r->fast; + if (val) r->fast = !!*val; +#endif + break; + + case GSM_OPT_FRAME_CHAIN: + +#ifdef WAV49 + result = r->frame_chain; + if (val) r->frame_chain = *val; +#endif + break; + + case GSM_OPT_FRAME_INDEX: + +#ifdef WAV49 + result = r->frame_index; + if (val) r->frame_index = *val; +#endif + break; + + case GSM_OPT_WAV49: + +#ifdef WAV49 + result = r->wav_fmt; + if (val) r->wav_fmt = !!*val; +#endif + break; + + default: + break; + } + return result; +} diff --git a/libs/codec/gsm/src/gsm_print.c b/libs/codec/gsm/src/gsm_print.c new file mode 100644 index 0000000000..41657a02b1 --- /dev/null +++ b/libs/codec/gsm/src/gsm_print.c @@ -0,0 +1,167 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +int gsm_print P3((f, s, c), FILE * f, gsm s, gsm_byte * c) +{ + word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; + + /* GSM_MAGIC = (*c >> 4) & 0xF; */ + + if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; + + LARc[0] = (*c++ & 0xF) << 2; /* 1 */ + LARc[0] |= (*c >> 6) & 0x3; + LARc[1] = *c++ & 0x3F; + LARc[2] = (*c >> 3) & 0x1F; + LARc[3] = (*c++ & 0x7) << 2; + LARc[3] |= (*c >> 6) & 0x3; + LARc[4] = (*c >> 2) & 0xF; + LARc[5] = (*c++ & 0x3) << 2; + LARc[5] |= (*c >> 6) & 0x3; + LARc[6] = (*c >> 3) & 0x7; + LARc[7] = *c++ & 0x7; + + + Nc[0] = (*c >> 1) & 0x7F; + bc[0] = (*c++ & 0x1) << 1; + bc[0] |= (*c >> 7) & 0x1; + Mc[0] = (*c >> 5) & 0x3; + xmaxc[0] = (*c++ & 0x1F) << 1; + xmaxc[0] |= (*c >> 7) & 0x1; + xmc[0] = (*c >> 4) & 0x7; + xmc[1] = (*c >> 1) & 0x7; + xmc[2] = (*c++ & 0x1) << 2; + xmc[2] |= (*c >> 6) & 0x3; + xmc[3] = (*c >> 3) & 0x7; + xmc[4] = *c++ & 0x7; + xmc[5] = (*c >> 5) & 0x7; + xmc[6] = (*c >> 2) & 0x7; + xmc[7] = (*c++ & 0x3) << 1; /* 10 */ + xmc[7] |= (*c >> 7) & 0x1; + xmc[8] = (*c >> 4) & 0x7; + xmc[9] = (*c >> 1) & 0x7; + xmc[10] = (*c++ & 0x1) << 2; + xmc[10] |= (*c >> 6) & 0x3; + xmc[11] = (*c >> 3) & 0x7; + xmc[12] = *c++ & 0x7; + + Nc[1] = (*c >> 1) & 0x7F; + bc[1] = (*c++ & 0x1) << 1; + bc[1] |= (*c >> 7) & 0x1; + Mc[1] = (*c >> 5) & 0x3; + xmaxc[1] = (*c++ & 0x1F) << 1; + xmaxc[1] |= (*c >> 7) & 0x1; + xmc[13] = (*c >> 4) & 0x7; + xmc[14] = (*c >> 1) & 0x7; + xmc[15] = (*c++ & 0x1) << 2; + xmc[15] |= (*c >> 6) & 0x3; + xmc[16] = (*c >> 3) & 0x7; + xmc[17] = *c++ & 0x7; + xmc[18] = (*c >> 5) & 0x7; + xmc[19] = (*c >> 2) & 0x7; + xmc[20] = (*c++ & 0x3) << 1; + xmc[20] |= (*c >> 7) & 0x1; + xmc[21] = (*c >> 4) & 0x7; + xmc[22] = (*c >> 1) & 0x7; + xmc[23] = (*c++ & 0x1) << 2; + xmc[23] |= (*c >> 6) & 0x3; + xmc[24] = (*c >> 3) & 0x7; + xmc[25] = *c++ & 0x7; + + + Nc[2] = (*c >> 1) & 0x7F; + bc[2] = (*c++ & 0x1) << 1; /* 20 */ + bc[2] |= (*c >> 7) & 0x1; + Mc[2] = (*c >> 5) & 0x3; + xmaxc[2] = (*c++ & 0x1F) << 1; + xmaxc[2] |= (*c >> 7) & 0x1; + xmc[26] = (*c >> 4) & 0x7; + xmc[27] = (*c >> 1) & 0x7; + xmc[28] = (*c++ & 0x1) << 2; + xmc[28] |= (*c >> 6) & 0x3; + xmc[29] = (*c >> 3) & 0x7; + xmc[30] = *c++ & 0x7; + xmc[31] = (*c >> 5) & 0x7; + xmc[32] = (*c >> 2) & 0x7; + xmc[33] = (*c++ & 0x3) << 1; + xmc[33] |= (*c >> 7) & 0x1; + xmc[34] = (*c >> 4) & 0x7; + xmc[35] = (*c >> 1) & 0x7; + xmc[36] = (*c++ & 0x1) << 2; + xmc[36] |= (*c >> 6) & 0x3; + xmc[37] = (*c >> 3) & 0x7; + xmc[38] = *c++ & 0x7; + + Nc[3] = (*c >> 1) & 0x7F; + bc[3] = (*c++ & 0x1) << 1; + bc[3] |= (*c >> 7) & 0x1; + Mc[3] = (*c >> 5) & 0x3; + xmaxc[3] = (*c++ & 0x1F) << 1; + xmaxc[3] |= (*c >> 7) & 0x1; + + xmc[39] = (*c >> 4) & 0x7; + xmc[40] = (*c >> 1) & 0x7; + xmc[41] = (*c++ & 0x1) << 2; + xmc[41] |= (*c >> 6) & 0x3; + xmc[42] = (*c >> 3) & 0x7; + xmc[43] = *c++ & 0x7; /* 30 */ + xmc[44] = (*c >> 5) & 0x7; + xmc[45] = (*c >> 2) & 0x7; + xmc[46] = (*c++ & 0x3) << 1; + xmc[46] |= (*c >> 7) & 0x1; + xmc[47] = (*c >> 4) & 0x7; + xmc[48] = (*c >> 1) & 0x7; + xmc[49] = (*c++ & 0x1) << 2; + xmc[49] |= (*c >> 6) & 0x3; + xmc[50] = (*c >> 3) & 0x7; + xmc[51] = *c & 0x7; /* 33 */ + + fprintf(f, + "LARc:\t%2.2d %2.2d %2.2d %2.2d %2.2d %2.2d %2.2d %2.2d\n", + LARc[0],LARc[1],LARc[2],LARc[3],LARc[4],LARc[5],LARc[6],LARc[7]); + + fprintf(f, "#1: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[0], bc[0], Mc[0], xmaxc[0]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[0],xmc[1],xmc[2],xmc[3],xmc[4],xmc[5],xmc[6], + xmc[7],xmc[8],xmc[9],xmc[10],xmc[11],xmc[12] ); + + fprintf(f, "#2: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[1], bc[1], Mc[1], xmaxc[1]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[13+0],xmc[13+1],xmc[13+2],xmc[13+3],xmc[13+4],xmc[13+5], + xmc[13+6], xmc[13+7],xmc[13+8],xmc[13+9],xmc[13+10],xmc[13+11], + xmc[13+12] ); + + fprintf(f, "#3: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[2], bc[2], Mc[2], xmaxc[2]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[26+0],xmc[26+1],xmc[26+2],xmc[26+3],xmc[26+4],xmc[26+5], + xmc[26+6], xmc[26+7],xmc[26+8],xmc[26+9],xmc[26+10],xmc[26+11], + xmc[26+12] ); + + fprintf(f, "#4: Nc %4.4d bc %d Mc %d xmaxc %d\n", + Nc[3], bc[3], Mc[3], xmaxc[3]); + fprintf(f, +"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n", + xmc[39+0],xmc[39+1],xmc[39+2],xmc[39+3],xmc[39+4],xmc[39+5], + xmc[39+6], xmc[39+7],xmc[39+8],xmc[39+9],xmc[39+10],xmc[39+11], + xmc[39+12] ); + + return 0; +} diff --git a/libs/codec/gsm/src/k6opt.h b/libs/codec/gsm/src/k6opt.h new file mode 100644 index 0000000000..2a4b118c23 --- /dev/null +++ b/libs/codec/gsm/src/k6opt.h @@ -0,0 +1,84 @@ +/* k6opt.h vector functions optimized for MMX extensions to x86 + * + * Copyright (C) 1999 by Stanley J. Brooks + * + * Any use of this software is permitted provided that this notice is not + * removed and that neither the authors nor the Technische Universitaet Berlin + * are deemed to have made any representations as to the suitability of this + * software for any purpose nor are held responsible for any defects of + * this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE; + * not even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. + * + * Chicago, 03.12.1999 + * Stanley J. Brooks + */ + +extern void Weighting_filter P2((e, x), + const word * e, /* signal [-5..0.39.44] IN */ + word * x /* signal [0..39] OUT */ +) +; + +extern longword k6maxcc P3((wt,dp,Nc_out), + const word *wt, + const word *dp, + word * Nc_out /* OUT */ +) +; +/* + * k6maxmin(p,n,out[]) + * input p[n] is array of shorts (require n>0) + * returns (long) maximum absolute value.. + * if out!=NULL, also returns out[0] the maximum and out[1] the minimum + */ +extern longword k6maxmin P3((p,n,out), + const word *p, + int n, + word *out /* out[0] is max, out[1] is min */ +) +; + +extern longword k6iprod P3((p,q,n), + const word *p, + const word *q, + int n +) +; + +/* + * k6vsraw(p,n,bits) + * input p[n] is array of shorts (require n>0) + * shift/round each to the right by bits>=0 bits. + */ +extern void k6vsraw P3((p,n,bits), + const word *p, + int n, + int bits +) +; + +/* + * k6vsllw(p,n,bits) + * input p[n] is array of shorts (require n>0) + * shift each to the left by bits>=0 bits. + */ +extern void k6vsllw P3((p,n,bits), + const word *p, + int n, + int bits +) +; + +#if 1 /* there isn't any significant speed gain from mmx here: */ +extern void Short_term_analysis_filteringx P4((u0,rp0,k_n,s), + register word * u0, + register word * rp0, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +; +/* +#define Short_term_analysis_filtering Short_term_analysis_filteringx +*/ +#endif diff --git a/libs/codec/gsm/src/k6opt.s b/libs/codec/gsm/src/k6opt.s new file mode 100644 index 0000000000..85d28e15b3 --- /dev/null +++ b/libs/codec/gsm/src/k6opt.s @@ -0,0 +1,739 @@ + .file "k6opt.s" + .version "01.01" +/* gcc2_compiled.: */ +.section .rodata + .align 4 + .type coefs,@object + .size coefs,24 +coefs: + .value -134 + .value -374 + .value 0 + .value 2054 + .value 5741 + .value 8192 + .value 5741 + .value 2054 + .value 0 + .value -374 + .value -134 + .value 0 +.text + .align 4 +/* void Weighting_filter (const short *e, short *x) */ +.globl Weighting_filter + .type Weighting_filter,@function +Weighting_filter: + pushl %ebp + movl %esp,%ebp + pushl %edi + pushl %esi + pushl %ebx + movl 12(%ebp),%edi + movl 8(%ebp),%ebx + addl $-10,%ebx + emms + movl $0x1000,%eax; movd %eax,%mm5 /* for rounding */ + movq coefs,%mm1 + movq coefs+8,%mm2 + movq coefs+16,%mm3 + xorl %esi,%esi + .p2align 2 +.L21: + movq (%ebx,%esi,2),%mm0 + pmaddwd %mm1,%mm0 + + movq 8(%ebx,%esi,2),%mm4 + pmaddwd %mm2,%mm4 + paddd %mm4,%mm0 + + movq 16(%ebx,%esi,2),%mm4 + pmaddwd %mm3,%mm4 + paddd %mm4,%mm0 + + movq %mm0,%mm4 + punpckhdq %mm0,%mm4 /* mm4 has high int32 of mm0 dup'd */ + paddd %mm4,%mm0; + + paddd %mm5,%mm0 /* add for roundoff */ + psrad $13,%mm0 + packssdw %mm0,%mm0 + movd %mm0,%eax /* ax has result */ + movw %ax,(%edi,%esi,2) + incl %esi + cmpl $39,%esi + jle .L21 + emms + popl %ebx + popl %esi + popl %edi + leave + ret +.Lfe1: + .size Weighting_filter,.Lfe1-Weighting_filter + +.macro ccstep n +.if \n + movq \n(%edi),%mm1 + movq \n(%esi),%mm2 +.else + movq (%edi),%mm1 + movq (%esi),%mm2 +.endif + pmaddwd %mm2,%mm1 + paddd %mm1,%mm0 +.endm + + .align 4 +/* long k6maxcc(const short *wt, const short *dp, short *Nc_out) */ +.globl k6maxcc + .type k6maxcc,@function +k6maxcc: + pushl %ebp + movl %esp,%ebp + pushl %edi + pushl %esi + pushl %ebx + emms + movl 8(%ebp),%edi + movl 12(%ebp),%esi + movl $0,%edx /* will be maximum inner-product */ + movl $40,%ebx + movl %ebx,%ecx /* will be index of max inner-product */ + subl $80,%esi + .p2align 2 +.L41: + movq (%edi),%mm0 + movq (%esi),%mm2 + pmaddwd %mm2,%mm0 + ccstep 8 + ccstep 16 + ccstep 24 + ccstep 32 + ccstep 40 + ccstep 48 + ccstep 56 + ccstep 64 + ccstep 72 + + movq %mm0,%mm1 + punpckhdq %mm0,%mm1 /* mm1 has high int32 of mm0 dup'd */ + paddd %mm1,%mm0; + movd %mm0,%eax /* eax has result */ + + cmpl %edx,%eax + jle .L40 + movl %eax,%edx + movl %ebx,%ecx + .p2align 2 +.L40: + subl $2,%esi + incl %ebx + cmpl $120,%ebx + jle .L41 + movl 16(%ebp),%eax + movw %cx,(%eax) + movl %edx,%eax + emms + popl %ebx + popl %esi + popl %edi + leave + ret +.Lfe2: + .size k6maxcc,.Lfe2-k6maxcc + + + .align 4 +/* long k6iprod (const short *p, const short *q, int n) */ +.globl k6iprod + .type k6iprod,@function +k6iprod: + pushl %ebp + movl %esp,%ebp + pushl %edi + pushl %esi + emms + pxor %mm0,%mm0 + movl 8(%ebp),%esi + movl 12(%ebp),%edi + movl 16(%ebp),%eax + leal -32(%esi,%eax,2),%edx /* edx = top - 32 */ + + cmpl %edx,%esi; ja .L202 + + .p2align 2 +.L201: + ccstep 0 + ccstep 8 + ccstep 16 + ccstep 24 + + addl $32,%esi + addl $32,%edi + cmpl %edx,%esi; jbe .L201 + + .p2align 2 +.L202: + addl $24,%edx /* now edx = top-8 */ + cmpl %edx,%esi; ja .L205 + + .p2align 2 +.L203: + ccstep 0 + + addl $8,%esi + addl $8,%edi + cmpl %edx,%esi; jbe .L203 + + .p2align 2 +.L205: + addl $4,%edx /* now edx = top-4 */ + cmpl %edx,%esi; ja .L207 + + movd (%edi),%mm1 + movd (%esi),%mm2 + pmaddwd %mm2,%mm1 + paddd %mm1,%mm0 + + addl $4,%esi + addl $4,%edi + + .p2align 2 +.L207: + addl $2,%edx /* now edx = top-2 */ + cmpl %edx,%esi; ja .L209 + + movswl (%edi),%eax + movd %eax,%mm1 + movswl (%esi),%eax + movd %eax,%mm2 + pmaddwd %mm2,%mm1 + paddd %mm1,%mm0 + + .p2align 2 +.L209: + movq %mm0,%mm1 + punpckhdq %mm0,%mm1 /* mm1 has high int32 of mm0 dup'd */ + paddd %mm1,%mm0; + movd %mm0,%eax /* eax has result */ + + emms + popl %esi + popl %edi + leave + ret +.Lfe3: + .size k6iprod,.Lfe3-k6iprod + + + .align 4 +/* void k6vsraw P3((short *p, int n, int bits) */ +.globl k6vsraw + .type k6vsraw,@function +k6vsraw: + pushl %ebp + movl %esp,%ebp + pushl %esi + movl 8(%ebp),%esi + movl 16(%ebp),%ecx + andl %ecx,%ecx; jle .L399 + movl 12(%ebp),%eax + leal -16(%esi,%eax,2),%edx /* edx = top - 16 */ + emms + movd %ecx,%mm3 + movq ones,%mm2 + psllw %mm3,%mm2; psrlw $1,%mm2 + cmpl %edx,%esi; ja .L306 + + .p2align 2 +.L302: /* 8 words per iteration */ + movq (%esi),%mm0 + movq 8(%esi),%mm1 + paddsw %mm2,%mm0 + psraw %mm3,%mm0; + paddsw %mm2,%mm1 + psraw %mm3,%mm1; + movq %mm0,(%esi) + movq %mm1,8(%esi) + addl $16,%esi + cmpl %edx,%esi + jbe .L302 + + .p2align 2 +.L306: + addl $12,%edx /* now edx = top-4 */ + cmpl %edx,%esi; ja .L310 + + .p2align 2 +.L308: /* do up to 6 words, two at a time */ + movd (%esi),%mm0 + paddsw %mm2,%mm0 + psraw %mm3,%mm0; + movd %mm0,(%esi) + addl $4,%esi + cmpl %edx,%esi + jbe .L308 + + .p2align 2 +.L310: + addl $2,%edx /* now edx = top-2 */ + cmpl %edx,%esi; ja .L315 + + movzwl (%esi),%eax + movd %eax,%mm0 + paddsw %mm2,%mm0 + psraw %mm3,%mm0; + movd %mm0,%eax + movw %ax,(%esi) + + .p2align 2 +.L315: + emms +.L399: + popl %esi + leave + ret +.Lfe4: + .size k6vsraw,.Lfe4-k6vsraw + + .align 4 +/* void k6vsllw P3((short *p, int n, int bits) */ +.globl k6vsllw + .type k6vsllw,@function +k6vsllw: + pushl %ebp + movl %esp,%ebp + pushl %esi + movl 8(%ebp),%esi + movl 16(%ebp),%ecx + andl %ecx,%ecx; jle .L499 + movl 12(%ebp),%eax + leal -16(%esi,%eax,2),%edx /* edx = top - 16 */ + emms + movd %ecx,%mm3 + cmpl %edx,%esi; ja .L406 + + .p2align 2 +.L402: /* 8 words per iteration */ + movq (%esi),%mm0 + movq 8(%esi),%mm1 + psllw %mm3,%mm0; + psllw %mm3,%mm1; + movq %mm0,(%esi) + movq %mm1,8(%esi) + addl $16,%esi + cmpl %edx,%esi + jbe .L402 + + .p2align 2 +.L406: + addl $12,%edx /* now edx = top-4 */ + cmpl %edx,%esi; ja .L410 + + .p2align 2 +.L408: /* do up to 6 words, two at a time */ + movd (%esi),%mm0 + psllw %mm3,%mm0; + movd %mm0,(%esi) + addl $4,%esi + cmpl %edx,%esi + jbe .L408 + + .p2align 2 +.L410: + addl $2,%edx /* now edx = top-2 */ + cmpl %edx,%esi; ja .L415 + + movzwl (%esi),%eax + movd %eax,%mm0 + psllw %mm3,%mm0; + movd %mm0,%eax + movw %ax,(%esi) + + .p2align 2 +.L415: + emms +.L499: + popl %esi + leave + ret +.Lfe5: + .size k6vsllw,.Lfe5-k6vsllw + + +.section .rodata + .align 4 + .type extremes,@object + .size extremes,8 +extremes: + .long 0x80008000 + .long 0x7fff7fff + .type ones,@object + .size ones,8 +ones: + .long 0x00010001 + .long 0x00010001 + +.text + .align 4 +/* long k6maxmin (const short *p, int n, short *out) */ +.globl k6maxmin + .type k6maxmin,@function +k6maxmin: + pushl %ebp + movl %esp,%ebp + pushl %esi + emms + movl 8(%ebp),%esi + movl 12(%ebp),%eax + leal -8(%esi,%eax,2),%edx + + cmpl %edx,%esi + jbe .L52 + movd extremes,%mm0 + movd extremes+4,%mm1 + jmp .L58 + + .p2align 2 +.L52: + movq (%esi),%mm0 /* mm0 will be max's */ + movq %mm0,%mm1 /* mm1 will be min's */ + addl $8,%esi + cmpl %edx,%esi + ja .L56 + + .p2align 2 +.L54: + movq (%esi),%mm2 + + movq %mm2,%mm3 + pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */ + movq %mm3,%mm4 + pand %mm2,%mm3 /* mm3 is mm2 masked to new max's */ + pandn %mm0,%mm4 /* mm4 is mm0 masked to its max's */ + por %mm3,%mm4 + movq %mm4,%mm0 /* now mm0 is updated max's */ + + movq %mm1,%mm3 + pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */ + pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */ + por %mm3,%mm2 + movq %mm2,%mm1 /* now mm1 is updated min's */ + + addl $8,%esi + cmpl %edx,%esi + jbe .L54 + + .p2align 2 +.L56: /* merge down the 4-word max/mins to lower 2 words */ + + movq %mm0,%mm2 + psrlq $32,%mm2 + movq %mm2,%mm3 + pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new max's */ + pandn %mm0,%mm3 /* mm3 is mm0 masked to its max's */ + por %mm3,%mm2 + movq %mm2,%mm0 /* now mm0 is updated max's */ + + movq %mm1,%mm2 + psrlq $32,%mm2 + movq %mm1,%mm3 + pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */ + pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */ + por %mm3,%mm2 + movq %mm2,%mm1 /* now mm1 is updated min's */ + + .p2align 2 +.L58: + addl $4,%edx /* now dx = top-4 */ + cmpl %edx,%esi + ja .L62 + /* here, there are >= 2 words of input remaining */ + movd (%esi),%mm2 + + movq %mm2,%mm3 + pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */ + movq %mm3,%mm4 + pand %mm2,%mm3 /* mm3 is mm2 masked to new max's */ + pandn %mm0,%mm4 /* mm4 is mm0 masked to its max's */ + por %mm3,%mm4 + movq %mm4,%mm0 /* now mm0 is updated max's */ + + movq %mm1,%mm3 + pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */ + pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */ + por %mm3,%mm2 + movq %mm2,%mm1 /* now mm1 is updated min's */ + + addl $4,%esi + + .p2align 2 +.L62: + /* merge down the 2-word max/mins to 1 word */ + + movq %mm0,%mm2 + psrlq $16,%mm2 + movq %mm2,%mm3 + pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new max's */ + pandn %mm0,%mm3 /* mm3 is mm0 masked to its max's */ + por %mm3,%mm2 + movd %mm2,%ecx /* cx is max so far */ + + movq %mm1,%mm2 + psrlq $16,%mm2 + movq %mm1,%mm3 + pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */ + pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */ + pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */ + por %mm3,%mm2 + movd %mm2,%eax /* ax is min so far */ + + addl $2,%edx /* now dx = top-2 */ + cmpl %edx,%esi + ja .L65 + + /* here, there is one word of input left */ + cmpw (%esi),%cx + jge .L64 + movw (%esi),%cx + .p2align 2 +.L64: + cmpw (%esi),%ax + jle .L65 + movw (%esi),%ax + + .p2align 2 +.L65: /* (finally!) cx is the max, ax the min */ + movswl %cx,%ecx + movswl %ax,%eax + + movl 16(%ebp),%edx /* ptr to output max,min vals */ + andl %edx,%edx; jz .L77 + movw %cx,(%edx) /* max */ + movw %ax,2(%edx) /* min */ + .p2align 2 +.L77: + /* now calculate max absolute val */ + negl %eax + cmpl %ecx,%eax + jge .L81 + movl %ecx,%eax + .p2align 2 +.L81: + emms + popl %esi + leave + ret +.Lfe6: + .size k6maxmin,.Lfe6-k6maxmin + +/* void Short_term_analysis_filtering (short *u0, const short *rp0, int kn, short *s) */ + .equiv pm_u0,8 + .equiv pm_rp0,12 + .equiv pm_kn,16 + .equiv pm_s,20 + .equiv lv_u_top,-4 + .equiv lv_s_top,-8 + .equiv lv_rp,-40 /* local version of rp0 with each word twice */ + .align 4 +.globl Short_term_analysis_filteringx + .type Short_term_analysis_filteringx,@function +Short_term_analysis_filteringx: + pushl %ebp + movl %esp,%ebp + subl $40,%esp + pushl %edi + pushl %esi + + movl pm_rp0(%ebp),%esi; + leal lv_rp(%ebp),%edi; + cld + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + emms + movl $0x4000,%eax; + movd %eax,%mm4; + punpckldq %mm4,%mm4 /* (0x00004000,0x00004000) for rounding dword product pairs */ + + movl pm_u0(%ebp),%eax + addl $16,%eax + movl %eax,lv_u_top(%ebp) /* UTOP */ + movl pm_s(%ebp),%edx /* edx is local s ptr throughout below */ + movl pm_kn(%ebp),%eax + leal (%edx,%eax,2),%eax + movl %eax,lv_s_top(%ebp) + cmpl %eax,%edx + jae .L179 + .p2align 2 +.L181: + leal lv_rp(%ebp),%esi /* RP */ + movl pm_u0(%ebp),%edi /* U */ + movw (%edx),%ax /* (0,DI) */ + roll $16,%eax + movw (%edx),%ax /* (DI,DI) */ + .p2align 2 +.L185: /* RP is %esi */ + movl %eax,%ecx + movw (%edi),%ax /* (DI,U) */ + movd (%esi),%mm3 /* mm3 is (0,0,RP,RP) */ + movw %cx,(%edi) + + movd %eax,%mm2 /* mm2 is (0,0,DI,U) */ + rorl $16,%eax + movd %eax,%mm1 /* mm1 is (0,0,U,DI) */ + + movq %mm1,%mm0 + pmullw %mm3,%mm0 + pmulhw %mm3,%mm1 + punpcklwd %mm1,%mm0 /* mm0 is (RP*U,RP*DI) */ + paddd %mm4,%mm0 /* mm4 is 0x00004000,0x00004000 */ + psrad $15,%mm0 /* (RP*U,RP*DI) adjusted */ + packssdw %mm0,%mm0 /* (*,*,RP*U,RP*DI) adjusted and saturated to word */ + paddsw %mm2,%mm0 /* mm0 is (?,?, DI', U') */ + movd %mm0,%eax /* (DI,U') */ + + addl $2,%edi + addl $4,%esi + cmpl lv_u_top(%ebp),%edi + jb .L185 + + rorl $16,%eax + movw %ax,(%edx) /* last DI goes to *s */ + addl $2,%edx /* next s */ + cmpl lv_s_top(%ebp),%edx + jb .L181 + .p2align 2 +.L179: + emms + popl %esi + popl %edi + leave + ret +.Lfe7: + .size Short_term_analysis_filteringx,.Lfe7-Short_term_analysis_filteringx + +.end + +/* 'as' macro's seem to be case-insensitive */ +.macro STEP n +.if \n + movd \n(%esi),%mm3 /* mm3 is (0,0,RP,RP) */ +.else + movd (%esi),%mm3 /* mm3 is (0,0,RP,RP) */ +.endif + movq %mm5,%mm1; + movd %mm4,%ecx; movw %cx,%ax /* (DI,U) */ + psllq $48,%mm1; psrlq $16,%mm4; por %mm1,%mm4 + psllq $48,%mm0; psrlq $16,%mm5; por %mm0,%mm5 + + movd %eax,%mm2 /* mm2 is (0,0,DI,U) */ + rorl $16,%eax + movd %eax,%mm1 /* mm1 is (0,0,U,DI) */ + + movq %mm1,%mm0 + pmullw %mm3,%mm0 + pmulhw %mm3,%mm1 + punpcklwd %mm1,%mm0 /* mm0 is (RP*U,RP*DI) */ + paddd %mm6,%mm0 /* mm6 is 0x00004000,0x00004000 */ + psrad $15,%mm0 /* (RP*U,RP*DI) adjusted */ + packssdw %mm0,%mm0 /* (*,*,RP*U,RP*DI) adjusted and saturated to word */ + paddsw %mm2,%mm0 /* mm0 is (?,?, DI', U') */ + movd %mm0,%eax /* (DI,U') */ +.endm + +/* void Short_term_analysis_filtering (short *u0, const short *rp0, int kn, short *s) */ + .equiv pm_u0,8 + .equiv pm_rp0,12 + .equiv pm_kn,16 + .equiv pm_s,20 + .equiv lv_rp_top,-4 + .equiv lv_s_top,-8 + .equiv lv_rp,-40 /* local version of rp0 with each word twice */ + .align 4 +.globl Short_term_analysis_filteringx + .type Short_term_analysis_filteringx,@function +Short_term_analysis_filteringx: + pushl %ebp + movl %esp,%ebp + subl $56,%esp + pushl %edi + pushl %esi + pushl %ebx + + movl pm_rp0(%ebp),%esi; + leal lv_rp(%ebp),%edi; + cld + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + lodsw; stosw; stosw + movl %edi,lv_rp_top(%ebp) + emms + + movl $0x4000,%eax; + movd %eax,%mm6; + punpckldq %mm6,%mm6 /* (0x00004000,0x00004000) for rounding dword product pairs */ + + movl pm_u0(%ebp),%ebx + movq (%ebx),%mm4; movq 8(%ebx),%mm5 /* the 8 u's */ + movl pm_s(%ebp),%edx /* edx is local s ptr throughout below */ + movl pm_kn(%ebp),%eax + leal (%edx,%eax,2),%eax + movl %eax,lv_s_top(%ebp) + cmpl %eax,%edx + jae .L179 + .p2align 2 +.L181: + leal lv_rp(%ebp),%esi /* RP */ + movw (%edx),%ax /* (0,DI) */ + roll $16,%eax + movw (%edx),%ax /* (DI,DI) */ + movd %eax,%mm0 + .p2align 2 +.L185: /* RP is %esi */ + step 0 + step 4 + step 8 + step 12 +/* + step 16 + step 20 + step 24 + step 28 +*/ + addl $16,%esi + cmpl lv_rp_top(%ebp),%esi + jb .L185 + + rorl $16,%eax + movw %ax,(%edx) /* last DI goes to *s */ + addl $2,%edx /* next s */ + cmpl lv_s_top(%ebp),%edx + jb .L181 +.L179: + movq %mm4,(%ebx); movq %mm5,8(%ebx) /* the 8 u's */ + emms + popl %ebx + popl %esi + popl %edi + leave + ret +.Lfe7: + .size Short_term_analysis_filteringx,.Lfe7-Short_term_analysis_filteringx + .ident "GCC: (GNU) 2.95.2 19991109 (Debian GNU/Linux)" diff --git a/libs/codec/gsm/src/long_term.c b/libs/codec/gsm/src/long_term.c new file mode 100644 index 0000000000..b8d6601ed6 --- /dev/null +++ b/libs/codec/gsm/src/long_term.c @@ -0,0 +1,952 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" +#ifdef K6OPT +#include "k6opt.h" +#endif +/* + * 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION + */ + + +/* + * This module computes the LTP gain (bc) and the LTP lag (Nc) + * for the long term analysis filter. This is done by calculating a + * maximum of the cross-correlation function between the current + * sub-segment short term residual signal d[0..39] (output of + * the short term analysis filter; for simplification the index + * of this array begins at 0 and ends at 39 for each sub-segment of the + * RPE-LTP analysis) and the previous reconstructed short term + * residual signal dp[ -120 .. -1 ]. A dynamic scaling must be + * performed to avoid overflow. + */ + + /* The next procedure exists in six versions. First two integer + * version (if USE_FLOAT_MUL is not defined); then four floating + * point versions, twice with proper scaling (USE_FLOAT_MUL defined), + * once without (USE_FLOAT_MUL and FAST defined, and fast run-time + * option used). Every pair has first a Cut version (see the -C + * option to toast or the LTP_CUT option to gsm_option()), then the + * uncut one. (For a detailed explanation of why this is altogether + * a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered + * Harmful''.) + */ + +#ifndef USE_FLOAT_MUL + +#ifdef LTP_CUT + +static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), + + struct gsm_state * st, + + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word wt[40]; + + longword L_result; + longword L_max, L_power; + word R, S, dmax, scal, best_k; + word ltp_cut; + + register word temp, wt_k; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) { + dmax = temp; + best_k = k; + } + } + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + if (temp > 6) scal = 0; + else scal = 6 - temp; + assert(scal >= 0); + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + wt_k = SASR(d[best_k], scal); + + for (lambda = 40; lambda <= 120; lambda++) { + L_result = (longword)wt_k * dp[best_k - lambda]; + if (L_result > L_max) { + Nc = lambda; + L_max = L_result; + } + } + *Nc_out = Nc; + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word wt[40]; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + + /* Initialization of a working array wt + */ + + for (k = 0; k <= 39; k++) wt[k] = SASR( d[k], scal ); + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ +# ifdef K6OPT + L_max = k6maxcc(wt,dp,&Nc); +# else + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda++) { + +# undef STEP +# define STEP(k) (longword)wt[k] * dp[k - lambda] + + register longword L_result; + + L_result = STEP(0) ; L_result += STEP(1) ; + L_result += STEP(2) ; L_result += STEP(3) ; + L_result += STEP(4) ; L_result += STEP(5) ; + L_result += STEP(6) ; L_result += STEP(7) ; + L_result += STEP(8) ; L_result += STEP(9) ; + L_result += STEP(10) ; L_result += STEP(11) ; + L_result += STEP(12) ; L_result += STEP(13) ; + L_result += STEP(14) ; L_result += STEP(15) ; + L_result += STEP(16) ; L_result += STEP(17) ; + L_result += STEP(18) ; L_result += STEP(19) ; + L_result += STEP(20) ; L_result += STEP(21) ; + L_result += STEP(22) ; L_result += STEP(23) ; + L_result += STEP(24) ; L_result += STEP(25) ; + L_result += STEP(26) ; L_result += STEP(27) ; + L_result += STEP(28) ; L_result += STEP(29) ; + L_result += STEP(30) ; L_result += STEP(31) ; + L_result += STEP(32) ; L_result += STEP(33) ; + L_result += STEP(34) ; L_result += STEP(35) ; + L_result += STEP(36) ; L_result += STEP(37) ; + L_result += STEP(38) ; L_result += STEP(39) ; + + if (L_result > L_max) { + + Nc = lambda; + L_max = L_result; + } + } +# endif + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#else /* USE_FLOAT_MUL */ + +#ifdef LTP_CUT + +static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), + struct gsm_state * st, /* IN */ + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + word ltp_cut; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + ltp_cut = (longword)SASR(dmax, scal) * st->ltp_cut / 100; + + + /* Initialization of a working array wt + */ + + for (k = 0; k < 40; k++) { + register word w = SASR( d[k], scal ); + if (w < 0 ? w > -ltp_cut : w < ltp_cut) { + wt_float[k] = 0.0; + } + else { + wt_float[k] = w; + } + } + for (k = -120; k < 0; k++) dp_float[k] = dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + if ((W = wt_float[K]) != 0.0) { \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E; } else (a = lp[K]) + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + + } + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + longword L_max, L_power; + word R, S, dmax, scal; + register word temp; + + /* Search of the optimum scaling of d[0..39]. + */ + dmax = 0; + + for (k = 0; k <= 39; k++) { + temp = d[k]; + temp = GSM_ABS( temp ); + if (temp > dmax) dmax = temp; + } + + temp = 0; + if (dmax == 0) scal = 0; + else { + assert(dmax > 0); + temp = gsm_norm( (longword)dmax << 16 ); + } + + if (temp > 6) scal = 0; + else scal = 6 - temp; + + assert(scal >= 0); + + /* Initialization of a working array wt + */ + + for (k = 0; k < 40; k++) wt_float[k] = SASR( d[k], scal ); + for (k = -120; k < 0; k++) dp_float[k] = dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + W = wt_float[K]; \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + } + *Nc_out = Nc; + + L_max <<= 1; + + /* Rescaling of L_max + */ + assert(scal <= 100 && scal >= -100); + L_max = L_max >> (6 - scal); /* sub(6, scal) */ + + assert( Nc <= 120 && Nc >= 40); + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + L_power = 0; + for (k = 0; k <= 39; k++) { + + register longword L_temp; + + L_temp = SASR( dp[k - Nc], 3 ); + L_power += L_temp * L_temp; + } + L_power <<= 1; /* from L_MULT */ + + /* Normalization of L_max and L_power + */ + + if (L_max <= 0) { + *bc_out = 0; + return; + } + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + temp = gsm_norm( L_power ); + + R = SASR( L_max << temp, 16 ); + S = SASR( L_power << temp, 16 ); + + /* Coding of the LTP gain + */ + + /* Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; + *bc_out = bc; +} + +#ifdef FAST +#ifdef LTP_CUT + +static void Cut_Fast_Calculation_of_the_LTP_parameters P5((st, + d,dp,bc_out,Nc_out), + struct gsm_state * st, /* IN */ + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + register float wt_float; + word Nc, bc; + word wt_max, best_k, ltp_cut; + + float dp_float_base[120], * dp_float = dp_float_base + 120; + + register float L_result, L_max, L_power; + + wt_max = 0; + + for (k = 0; k < 40; ++k) { + if ( d[k] > wt_max) wt_max = d[best_k = k]; + else if (-d[k] > wt_max) wt_max = -d[best_k = k]; + } + + assert(wt_max >= 0); + wt_float = (float)wt_max; + + for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda++) { + L_result = wt_float * dp_float[best_k - lambda]; + if (L_result > L_max) { + Nc = lambda; + L_max = L_result; + } + } + + *Nc_out = Nc; + if (L_max <= 0.) { + *bc_out = 0; + return; + } + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + dp_float -= Nc; + L_power = 0; + for (k = 0; k < 40; ++k) { + register float f = dp_float[k]; + L_power += f * f; + } + + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + /* Coding of the LTP gain + * Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + lambda = L_max / L_power * 32768.; + for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; + *bc_out = bc; +} + +#endif /* LTP_CUT */ + +static void Fast_Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), + register word * d, /* [0..39] IN */ + register word * dp, /* [-120..-1] IN */ + word * bc_out, /* OUT */ + word * Nc_out /* OUT */ +) +{ + register int k, lambda; + word Nc, bc; + + float wt_float[40]; + float dp_float_base[120], * dp_float = dp_float_base + 120; + + register float L_max, L_power; + + for (k = 0; k < 40; ++k) wt_float[k] = (float)d[k]; + for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; + + /* Search for the maximum cross-correlation and coding of the LTP lag + */ + L_max = 0; + Nc = 40; /* index for the maximum cross-correlation */ + + for (lambda = 40; lambda <= 120; lambda += 9) { + + /* Calculate L_result for l = lambda .. lambda + 9. + */ + register float *lp = dp_float - lambda; + + register float W; + register float a = lp[-8], b = lp[-7], c = lp[-6], + d = lp[-5], e = lp[-4], f = lp[-3], + g = lp[-2], h = lp[-1]; + register float E; + register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, + S5 = 0, S6 = 0, S7 = 0, S8 = 0; + +# undef STEP +# define STEP(K, a, b, c, d, e, f, g, h) \ + W = wt_float[K]; \ + E = W * a; S8 += E; \ + E = W * b; S7 += E; \ + E = W * c; S6 += E; \ + E = W * d; S5 += E; \ + E = W * e; S4 += E; \ + E = W * f; S3 += E; \ + E = W * g; S2 += E; \ + E = W * h; S1 += E; \ + a = lp[K]; \ + E = W * a; S0 += E + +# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) +# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) +# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) +# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) +# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) +# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) +# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) +# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) + + STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); + STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); + + STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); + STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); + + STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); + STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); + + STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); + STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); + + STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); + STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); + + if (S0 > L_max) { L_max = S0; Nc = lambda; } + if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } + if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } + if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } + if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } + if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } + if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } + if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } + if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } + } + *Nc_out = Nc; + + if (L_max <= 0.) { + *bc_out = 0; + return; + } + + /* Compute the power of the reconstructed short term residual + * signal dp[..] + */ + dp_float -= Nc; + L_power = 0; + for (k = 0; k < 40; ++k) { + register float f = dp_float[k]; + L_power += f * f; + } + + if (L_max >= L_power) { + *bc_out = 3; + return; + } + + /* Coding of the LTP gain + * Table 4.3a must be used to obtain the level DLB[i] for the + * quantization of the LTP gain b to get the coded version bc. + */ + lambda = L_max / L_power * 32768.; + for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; + *bc_out = bc; +} + +#endif /* FAST */ +#endif /* USE_FLOAT_MUL */ + + +/* 4.2.12 */ + +static void Long_term_analysis_filtering P6((bc,Nc,dp,d,dpp,e), + word bc, /* IN */ + word Nc, /* IN */ + register word * dp, /* previous d [-120..-1] IN */ + register word * d, /* d [0..39] IN */ + register word * dpp, /* estimate [0..39] OUT */ + register word * e /* long term res. signal [0..39] OUT */ +) +/* + * In this part, we have to decode the bc parameter to compute + * the samples of the estimate dpp[0..39]. The decoding of bc needs the + * use of table 4.3b. The long term residual signal e[0..39] + * is then calculated to be fed to the RPE encoding section. + */ +{ + register int k; + +# undef STEP +# define STEP(BP) \ + for (k = 0; k <= 39; k++) { \ + dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \ + e[k] = GSM_SUB( d[k], dpp[k] ); \ + } + + switch (bc) { + case 0: STEP( 3277 ); break; + case 1: STEP( 11469 ); break; + case 2: STEP( 21299 ); break; + case 3: STEP( 32767 ); break; + } +} + +void Gsm_Long_Term_Predictor P7((S,d,dp,e,dpp,Nc,bc), /* 4x for 160 samples */ + + struct gsm_state * S, + + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + + word * e, /* [0..39] OUT */ + word * dpp, /* [0..39] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc /* gain factor OUT */ +) +{ + assert( d ); assert( dp ); assert( e ); + assert( dpp); assert( Nc ); assert( bc ); + +#if defined(FAST) && defined(USE_FLOAT_MUL) + if (S->fast) +#if defined (LTP_CUT) + if (S->ltp_cut) + Cut_Fast_Calculation_of_the_LTP_parameters(S, + d, dp, bc, Nc); + else +#endif /* LTP_CUT */ + Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc ); + else +#endif /* FAST & USE_FLOAT_MUL */ +#ifdef LTP_CUT + if (S->ltp_cut) + Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); + else +#endif + Calculation_of_the_LTP_parameters(d, dp, bc, Nc); + + Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e ); +} + +/* 4.3.2 */ +void Gsm_Long_Term_Synthesis_Filtering P5((S,Ncr,bcr,erp,drp), + struct gsm_state * S, + + word Ncr, + word bcr, + register word * erp, /* [0..39] IN */ + register word * drp /* [-120..-1] IN, [-120..40] OUT */ +) +/* + * This procedure uses the bcr and Ncr parameter to realize the + * long term synthesis filtering. The decoding of bcr needs + * table 4.3b. + */ +{ + register int k; + word brp, drpp, Nr; + + /* Check the limits of Nr. + */ + Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr; + S->nrp = Nr; + assert(Nr >= 40 && Nr <= 120); + + /* Decoding of the LTP gain bcr + */ + brp = gsm_QLB[ bcr ]; + + /* Computation of the reconstructed short term residual + * signal drp[0..39] + */ + assert(brp != MIN_WORD); + + for (k = 0; k <= 39; k++) { + drpp = GSM_MULT_R( brp, drp[ k - Nr ] ); + drp[k] = GSM_ADD( erp[k], drpp ); + } + + /* + * Update of the reconstructed short term residual signal + * drp[ -1..-120 ] + */ + + for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ]; +} diff --git a/libs/codec/gsm/src/lpc.c b/libs/codec/gsm/src/lpc.c new file mode 100644 index 0000000000..9e2e15363e --- /dev/null +++ b/libs/codec/gsm/src/lpc.c @@ -0,0 +1,369 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +#ifdef K6OPT +#include "k6opt.h" +#endif + +#undef P + +/* + * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION + */ + +/* 4.2.4 */ + + +static void Autocorrelation P2((s, L_ACF), + word * s, /* [0..159] IN/OUT */ + longword * L_ACF) /* [0..8] OUT */ +/* + * The goal is to compute the array L_ACF[k]. The signal s[i] must + * be scaled in order to avoid an overflow situation. + */ +{ + register int k, i; + + word temp, smax, scalauto; + +#ifdef USE_FLOAT_MUL + float float_s[160]; +#endif + + /* Dynamic scaling of the array s[0..159] + */ + + /* Search for the maximum. + */ +#ifndef K6OPT + smax = 0; + for (k = 0; k <= 159; k++) { + temp = GSM_ABS( s[k] ); + if (temp > smax) smax = temp; + } +#else + { + longword lmax; + lmax = k6maxmin(s,160,NULL); + smax = (lmax > MAX_WORD) ? MAX_WORD : lmax; + } +#endif + /* Computation of the scaling factor. + */ + if (smax == 0) scalauto = 0; + else { + assert(smax > 0); + scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ + } + + /* Scaling of the array s[0...159] + */ + + if (scalauto > 0) { +# ifndef K6OPT + +# ifdef USE_FLOAT_MUL +# define SCALE(n) \ + case n: for (k = 0; k <= 159; k++) \ + float_s[k] = (float) \ + (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ + break; +# else +# define SCALE(n) \ + case n: for (k = 0; k <= 159; k++) \ + s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ + break; +# endif /* USE_FLOAT_MUL */ + + switch (scalauto) { + SCALE(1) + SCALE(2) + SCALE(3) + SCALE(4) + } +# undef SCALE + +# else /* K6OPT */ + k6vsraw(s,160,scalauto); +# endif + } +# ifdef USE_FLOAT_MUL + else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; +# endif + + /* Compute the L_ACF[..]. + */ +#ifndef K6OPT + { +# ifdef USE_FLOAT_MUL + register float * sp = float_s; + register float sl = *sp; + +# define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); +# else + word * sp = s; + word sl = *sp; + +# define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); +# endif + +# define NEXTI sl = *++sp + + + for (k = 9; k--; L_ACF[k] = 0) ; + + STEP (0); + NEXTI; + STEP(0); STEP(1); + NEXTI; + STEP(0); STEP(1); STEP(2); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); + NEXTI; + STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); + + for (i = 8; i <= 159; i++) { + + NEXTI; + + STEP(0); + STEP(1); STEP(2); STEP(3); STEP(4); + STEP(5); STEP(6); STEP(7); STEP(8); + } + + for (k = 9; k--; L_ACF[k] <<= 1) ; + + } + +#else + { + int k; + for (k=0; k<9; k++) { + L_ACF[k] = 2*k6iprod(s,s+k,160-k); + } + } +#endif + /* Rescaling of the array s[0..159] + */ + if (scalauto > 0) { + assert(scalauto <= 4); +#ifndef K6OPT + for (k = 160; k--; *s++ <<= scalauto) ; +# else /* K6OPT */ + k6vsllw(s,160,scalauto); +# endif + } +} + +#if defined(USE_FLOAT_MUL) && defined(FAST) + +static void Fast_Autocorrelation P2((s, L_ACF), + word * s, /* [0..159] IN/OUT */ + longword * L_ACF) /* [0..8] OUT */ +{ + register int k, i; + float f_L_ACF[9]; + float scale; + + float s_f[160]; + register float *sf = s_f; + + for (i = 0; i < 160; ++i) sf[i] = s[i]; + for (k = 0; k <= 8; k++) { + register float L_temp2 = 0; + register float *sfl = sf - k; + for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i]; + f_L_ACF[k] = L_temp2; + } + scale = MAX_LONGWORD / f_L_ACF[0]; + + for (k = 0; k <= 8; k++) { + L_ACF[k] = f_L_ACF[k] * scale; + } +} +#endif /* defined (USE_FLOAT_MUL) && defined (FAST) */ + +/* 4.2.5 */ + +static void Reflection_coefficients P2( (L_ACF, r), + longword * L_ACF, /* 0...8 IN */ + register word * r /* 0...7 OUT */ +) +{ + register int i, m, n; + register word temp; + word ACF[9]; /* 0..8 */ + word P[ 9]; /* 0..8 */ + word K[ 9]; /* 2..8 */ + + /* Schur recursion with 16 bits arithmetic. + */ + + if (L_ACF[0] == 0) { + for (i = 8; i--; *r++ = 0) ; + return; + } + + assert( L_ACF[0] != 0 ); + temp = gsm_norm( L_ACF[0] ); + + assert(temp >= 0 && temp < 32); + + /* ? overflow ? */ + for (i = 0; i <= 8; i++) ACF[i] = SASR( L_ACF[i] << temp, 16 ); + + /* Initialize array P[..] and K[..] for the recursion. + */ + + for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; + for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; + + /* Compute reflection coefficients + */ + for (n = 1; n <= 8; n++, r++) { + + temp = P[1]; + temp = GSM_ABS(temp); + if (P[0] < temp) { + for (i = n; i <= 8; i++) *r++ = 0; + return; + } + + *r = gsm_div( temp, P[0] ); + + assert(*r >= 0); + if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ + assert (*r != MIN_WORD); + if (n == 8) return; + + /* Schur recursion + */ + temp = GSM_MULT_R( P[1], *r ); + P[0] = GSM_ADD( P[0], temp ); + + for (m = 1; m <= 8 - n; m++) { + temp = GSM_MULT_R( K[ m ], *r ); + P[m] = GSM_ADD( P[ m+1 ], temp ); + + temp = GSM_MULT_R( P[ m+1 ], *r ); + K[m] = GSM_ADD( K[ m ], temp ); + } + } +} + +/* 4.2.6 */ + +static void Transformation_to_Log_Area_Ratios P1((r), + register word * r /* 0..7 IN/OUT */ +) +/* + * The following scaling for r[..] and LAR[..] has been used: + * + * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. + * LAR[..] = integer( real_LAR[..] * 16384 ); + * with -1.625 <= real_LAR <= 1.625 + */ +{ + register word temp; + register int i; + + + /* Computation of the LAR[0..7] from the r[0..7] + */ + for (i = 1; i <= 8; i++, r++) { + + temp = *r; + temp = GSM_ABS(temp); + assert(temp >= 0); + + if (temp < 22118) { + temp >>= 1; + } else if (temp < 31130) { + assert( temp >= 11059 ); + temp -= 11059; + } else { + assert( temp >= 26112 ); + temp -= 26112; + temp <<= 2; + } + + *r = *r < 0 ? -temp : temp; + assert( *r != MIN_WORD ); + } +} + +/* 4.2.7 */ + +static void Quantization_and_coding P1((LAR), + register word * LAR /* [0..7] IN/OUT */ +) +{ + register word temp; + + + /* This procedure needs four tables; the following equations + * give the optimum scaling for the constants: + * + * A[0..7] = integer( real_A[0..7] * 1024 ) + * B[0..7] = integer( real_B[0..7] * 512 ) + * MAC[0..7] = maximum of the LARc[0..7] + * MIC[0..7] = minimum of the LARc[0..7] + */ + +# undef STEP +# define STEP( A, B, MAC, MIC ) \ + temp = GSM_MULT( A, *LAR ); \ + temp = GSM_ADD( temp, B ); \ + temp = GSM_ADD( temp, 256 ); \ + temp = SASR( temp, 9 ); \ + *LAR = temp>MAC ? MAC - MIC : (tempfast) Fast_Autocorrelation (s, L_ACF ); + else +#endif + Autocorrelation (s, L_ACF ); + Reflection_coefficients (L_ACF, LARc ); + Transformation_to_Log_Area_Ratios (LARc); + Quantization_and_coding (LARc); +} diff --git a/libs/codec/gsm/src/preprocess.c b/libs/codec/gsm/src/preprocess.c new file mode 100644 index 0000000000..ed12ad299d --- /dev/null +++ b/libs/codec/gsm/src/preprocess.c @@ -0,0 +1,131 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION + * + * After A-law to linear conversion (or directly from the + * Ato D converter) the following scaling is assumed for + * input to the RPE-LTP algorithm: + * + * in: 0.1.....................12 + * S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.* + * + * Where S is the sign bit, v a valid bit, and * a "don't care" bit. + * The original signal is called sop[..] + * + * out: 0.1................... 12 + * S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0 + */ + + +void Gsm_Preprocess P3((S, s, so), + struct gsm_state * S, + word * s, + word * so ) /* [0..159] IN/OUT */ +{ + + word z1 = S->z1; + longword L_z2 = S->L_z2; + word mp = S->mp; + + word s1; + + + word SO; + + ulongword utmp; /* for L_ADD */ + + register int k = 160; + + while (k--) { + + /* 4.2.1 Downscaling of the input signal + */ + /* SO = SASR( *s, 3 ) << 2;*/ + SO = SASR( *s, 1 ) & ~3; + s++; + + assert (SO >= -0x4000); /* downscaled by */ + assert (SO <= 0x3FFC); /* previous routine. */ + + + /* 4.2.2 Offset compensation + * + * This part implements a high-pass filter and requires extended + * arithmetic precision for the recursive part of this filter. + * The input of this procedure is the array so[0...159] and the + * output the array sof[ 0...159 ]. + */ + /* Compute the non-recursive part + */ + + s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */ + z1 = SO; + + assert(s1 != MIN_WORD); + + /* SJB Remark: float might be faster than the mess that follows */ + + /* Compute the recursive part + */ + + /* Execution of a 31 bv 16 bits multiplication + */ + { + word msp; +#ifndef __GNUC__ + word lsp; +#endif + longword L_s2; + longword L_temp; + + L_s2 = s1; + L_s2 <<= 15; +#ifndef __GNUC__ + msp = SASR( L_z2, 15 ); + lsp = L_z2 & 0x7fff; /* gsm_L_sub(L_z2,(msp<<15)); */ + + L_s2 += GSM_MULT_R( lsp, 32735 ); + L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/ + L_z2 = GSM_L_ADD( L_temp, L_s2 ); + /* above does L_z2 = L_z2 * 0x7fd5/0x8000 + L_s2 */ +#else + L_z2 = ((long long)L_z2*32735 + 0x4000)>>15; + /* alternate (ansi) version of above line does slightly different rounding: + * L_temp = L_z2 >> 9; + * L_temp += L_temp >> 5; + * L_temp = (++L_temp) >> 1; + * L_z2 = L_z2 - L_temp; + */ + L_z2 = GSM_L_ADD(L_z2,L_s2); +#endif + /* Compute sof[k] with rounding + */ + L_temp = GSM_L_ADD( L_z2, 16384 ); + + /* 4.2.3 Preemphasis + */ + + msp = GSM_MULT_R( mp, -28180 ); + mp = SASR( L_temp, 15 ); + *so++ = GSM_ADD( mp, msp ); + } + } + + S->z1 = z1; + S->L_z2 = L_z2; + S->mp = mp; +} diff --git a/libs/codec/gsm/src/rpe.c b/libs/codec/gsm/src/rpe.c new file mode 100644 index 0000000000..7f3b7ebd45 --- /dev/null +++ b/libs/codec/gsm/src/rpe.c @@ -0,0 +1,490 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" + +/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION + */ + +/* 4.2.13 */ +#ifdef K6OPT +#include "k6opt.h" +#else +static void Weighting_filter P2((e, x), + register word * e, /* signal [-5..0.39.44] IN */ + word * x /* signal [0..39] OUT */ +) +/* + * The coefficients of the weighting filter are stored in a table + * (see table 4.4). The following scaling is used: + * + * H[0..10] = integer( real_H[ 0..10] * 8192 ); + */ +{ + /* word wt[ 50 ]; */ + + register longword L_result; + register int k /* , i */ ; + + /* Initialization of a temporary working array wt[0...49] + */ + + /* for (k = 0; k <= 4; k++) wt[k] = 0; + * for (k = 5; k <= 44; k++) wt[k] = *e++; + * for (k = 45; k <= 49; k++) wt[k] = 0; + * + * (e[-5..-1] and e[40..44] are allocated by the caller, + * are initially zero and are not written anywhere.) + */ + e -= 5; + + /* Compute the signal x[0..39] + */ + for (k = 0; k <= 39; k++) { + + L_result = 8192 >> 1; + + /* for (i = 0; i <= 10; i++) { + * L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] ); + * L_result = GSM_L_ADD( L_result, L_temp ); + * } + */ + +#undef STEP +#define STEP( i, H ) (e[ k + i ] * (longword)H) + + /* Every one of these multiplications is done twice -- + * but I don't see an elegant way to optimize this. + * Do you? + */ + +#ifdef STUPID_COMPILER + L_result += STEP( 0, -134 ) ; + L_result += STEP( 1, -374 ) ; + /* + STEP( 2, 0 ) */ + L_result += STEP( 3, 2054 ) ; + L_result += STEP( 4, 5741 ) ; + L_result += STEP( 5, 8192 ) ; + L_result += STEP( 6, 5741 ) ; + L_result += STEP( 7, 2054 ) ; + /* + STEP( 8, 0 ) */ + L_result += STEP( 9, -374 ) ; + L_result += STEP( 10, -134 ) ; +#else + L_result += + STEP( 0, -134 ) + + STEP( 1, -374 ) + /* + STEP( 2, 0 ) */ + + STEP( 3, 2054 ) + + STEP( 4, 5741 ) + + STEP( 5, 8192 ) + + STEP( 6, 5741 ) + + STEP( 7, 2054 ) + /* + STEP( 8, 0 ) */ + + STEP( 9, -374 ) + + STEP(10, -134 ) + ; +#endif + + /* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *) + * L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *) + * + * x[k] = SASR( L_result, 16 ); + */ + + /* 2 adds vs. >>16 => 14, minus one shift to compensate for + * those we lost when replacing L_MULT by '*'. + */ + + L_result = SASR( L_result, 13 ); + x[k] = ( L_result < MIN_WORD ? MIN_WORD + : (L_result > MAX_WORD ? MAX_WORD : L_result )); + } +} +#endif /* K6OPT */ + +/* 4.2.14 */ + +static void RPE_grid_selection P3((x,xM,Mc_out), + word * x, /* [0..39] IN */ + word * xM, /* [0..12] OUT */ + word * Mc_out /* OUT */ +) +/* + * The signal x[0..39] is used to select the RPE grid which is + * represented by Mc. + */ +{ + /* register word temp1; */ + register int /* m, */ i; + register longword L_result, L_temp; + longword EM; /* xxx should be L_EM? */ + word Mc; + + longword L_common_0_3; + + EM = 0; + Mc = 0; + + /* for (m = 0; m <= 3; m++) { + * L_result = 0; + * + * + * for (i = 0; i <= 12; i++) { + * + * temp1 = SASR( x[m + 3*i], 2 ); + * + * assert(temp1 != MIN_WORD); + * + * L_temp = GSM_L_MULT( temp1, temp1 ); + * L_result = GSM_L_ADD( L_temp, L_result ); + * } + * + * if (L_result > EM) { + * Mc = m; + * EM = L_result; + * } + * } + */ + +#undef STEP +#define STEP( m, i ) L_temp = SASR( x[m + 3 * i], 2 ); \ + L_result += L_temp * L_temp; + + /* common part of 0 and 3 */ + + L_result = 0; + STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 ); + STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 ); + STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12); + L_common_0_3 = L_result; + + /* i = 0 */ + + STEP( 0, 0 ); + L_result <<= 1; /* implicit in L_MULT */ + EM = L_result; + + /* i = 1 */ + + L_result = 0; + STEP( 1, 0 ); + STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 ); + STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 ); + STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12); + L_result <<= 1; + if (L_result > EM) { + Mc = 1; + EM = L_result; + } + + /* i = 2 */ + + L_result = 0; + STEP( 2, 0 ); + STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 ); + STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 ); + STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12); + L_result <<= 1; + if (L_result > EM) { + Mc = 2; + EM = L_result; + } + + /* i = 3 */ + + L_result = L_common_0_3; + STEP( 3, 12 ); + L_result <<= 1; + if (L_result > EM) { + Mc = 3; + EM = L_result; + } + + /**/ + + /* Down-sampling by a factor 3 to get the selected xM[0..12] + * RPE sequence. + */ + for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i]; + *Mc_out = Mc; +} + +/* 4.12.15 */ + +static void APCM_quantization_xmaxc_to_exp_mant P3((xmaxc,exp_out,mant_out), + word xmaxc, /* IN */ + word * exp_out, /* OUT */ + word * mant_out ) /* OUT */ +{ + word exp, mant; + + /* Compute exponent and mantissa of the decoded version of xmaxc + */ + + exp = 0; + if (xmaxc > 15) exp = SASR(xmaxc, 3) - 1; + mant = xmaxc - (exp << 3); + + if (mant == 0) { + exp = -4; + mant = 7; + } + else { + while (mant <= 7) { + mant = mant << 1 | 1; + exp--; + } + mant -= 8; + } + + assert( exp >= -4 && exp <= 6 ); + assert( mant >= 0 && mant <= 7 ); + + *exp_out = exp; + *mant_out = mant; +} + +static void APCM_quantization P5((xM,xMc,mant_out,exp_out,xmaxc_out), + word * xM, /* [0..12] IN */ + + word * xMc, /* [0..12] OUT */ + word * mant_out, /* OUT */ + word * exp_out, /* OUT */ + word * xmaxc_out /* OUT */ +) +{ + int i, itest; + + word xmax, xmaxc, temp, temp1, temp2; + word exp, mant; + + + /* Find the maximum absolute value xmax of xM[0..12]. + */ + + xmax = 0; + for (i = 0; i <= 12; i++) { + temp = xM[i]; + temp = GSM_ABS(temp); + if (temp > xmax) xmax = temp; + } + + /* Qantizing and coding of xmax to get xmaxc. + */ + + exp = 0; + temp = SASR( xmax, 9 ); + itest = 0; + + for (i = 0; i <= 5; i++) { + + itest |= (temp <= 0); + temp = SASR( temp, 1 ); + + assert(exp <= 5); + if (itest == 0) exp++; /* exp = add (exp, 1) */ + } + + assert(exp <= 6 && exp >= 0); + temp = exp + 5; + + assert(temp <= 11 && temp >= 0); + xmaxc = gsm_add( SASR(xmax, temp), exp << 3 ); + + /* Quantizing and coding of the xM[0..12] RPE sequence + * to get the xMc[0..12] + */ + + APCM_quantization_xmaxc_to_exp_mant( xmaxc, &exp, &mant ); + + /* This computation uses the fact that the decoded version of xmaxc + * can be calculated by using the exponent and the mantissa part of + * xmaxc (logarithmic table). + * So, this method avoids any division and uses only a scaling + * of the RPE samples by a function of the exponent. A direct + * multiplication by the inverse of the mantissa (NRFAC[0..7] + * found in table 4.5) gives the 3 bit coded version xMc[0..12] + * of the RPE samples. + */ + + + /* Direct computation of xMc[0..12] using table 4.5 + */ + + assert( exp <= 4096 && exp >= -4096); + assert( mant >= 0 && mant <= 7 ); + + temp1 = 6 - exp; /* normalization by the exponent */ + temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */ + + for (i = 0; i <= 12; i++) { + + assert(temp1 >= 0 && temp1 < 16); + + temp = xM[i] << temp1; + temp = GSM_MULT( temp, temp2 ); + temp = SASR(temp, 12); + xMc[i] = temp + 4; /* see note below */ + } + + /* NOTE: This equation is used to make all the xMc[i] positive. + */ + + *mant_out = mant; + *exp_out = exp; + *xmaxc_out = xmaxc; +} + +/* 4.2.16 */ + +static void APCM_inverse_quantization P4((xMc,mant,exp,xMp), + register word * xMc, /* [0..12] IN */ + word mant, + word exp, + register word * xMp) /* [0..12] OUT */ +/* + * This part is for decoding the RPE sequence of coded xMc[0..12] + * samples to obtain the xMp[0..12] array. Table 4.6 is used to get + * the mantissa of xmaxc (FAC[0..7]). + */ +{ + int i; + word temp, temp1, temp2, temp3; + + assert( mant >= 0 && mant <= 7 ); + + temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */ + temp2 = gsm_sub( 6, exp ); /* see 4.2-15 for exp */ + temp3 = gsm_asl( 1, gsm_sub( temp2, 1 )); + + for (i = 13; i--;) { + + assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */ + + /* temp = gsm_sub( *xMc++ << 1, 7 ); */ + temp = (*xMc++ << 1) - 7; /* restore sign */ + assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */ + + temp <<= 12; /* 16 bit signed */ + temp = GSM_MULT_R( temp1, temp ); + temp = GSM_ADD( temp, temp3 ); + *xMp++ = gsm_asr( temp, temp2 ); + } +} + +/* 4.2.17 */ + +static void RPE_grid_positioning P3((Mc,xMp,ep), + word Mc, /* grid position IN */ + register word * xMp, /* [0..12] IN */ + register word * ep /* [0..39] OUT */ +) +/* + * This procedure computes the reconstructed long term residual signal + * ep[0..39] for the LTP analysis filter. The inputs are the Mc + * which is the grid position selection and the xMp[0..12] decoded + * RPE samples which are upsampled by a factor of 3 by inserting zero + * values. + */ +{ + int i = 13; + + assert(0 <= Mc && Mc <= 3); + + switch (Mc) { + case 3: *ep++ = 0; + case 2: do { + *ep++ = 0; + case 1: *ep++ = 0; + case 0: *ep++ = *xMp++; + } while (--i); + } + while (++Mc < 4) *ep++ = 0; + + /* + + int i, k; + for (k = 0; k <= 39; k++) ep[k] = 0; + for (i = 0; i <= 12; i++) { + ep[ Mc + (3*i) ] = xMp[i]; + } + */ +} + +/* 4.2.18 */ + +/* This procedure adds the reconstructed long term residual signal + * ep[0..39] to the estimated signal dpp[0..39] from the long term + * analysis filter to compute the reconstructed short term residual + * signal dp[-40..-1]; also the reconstructed short term residual + * array dp[-120..-41] is updated. + */ + +#if 0 /* Has been inlined in code.c */ +void Gsm_Update_of_reconstructed_short_time_residual_signal P3((dpp, ep, dp), + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp) /* [-120...-1] IN/OUT */ +{ + int k; + + for (k = 0; k <= 79; k++) + dp[ -120 + k ] = dp[ -80 + k ]; + + for (k = 0; k <= 39; k++) + dp[ -40 + k ] = gsm_add( ep[k], dpp[k] ); +} +#endif /* Has been inlined in code.c */ + +void Gsm_RPE_Encoding P5((S,e,xmaxc,Mc,xMc), + + struct gsm_state * S, + + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc) /* [0..12] OUT */ +{ + word x[40]; + word xM[13], xMp[13]; + word mant, exp; + + Weighting_filter(e, x); + RPE_grid_selection(x, xM, Mc); + + APCM_quantization( xM, xMc, &mant, &exp, xmaxc); + APCM_inverse_quantization( xMc, mant, exp, xMp); + + RPE_grid_positioning( *Mc, xMp, e ); + +} + +void Gsm_RPE_Decoding P5((S, xmaxcr, Mcr, xMcr, erp), + struct gsm_state * S, + + word xmaxcr, + word Mcr, + word * xMcr, /* [0..12], 3 bits IN */ + word * erp /* [0..39] OUT */ +) +{ + word exp, mant; + word xMp[ 13 ]; + + APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &exp, &mant ); + APCM_inverse_quantization( xMcr, mant, exp, xMp ); + RPE_grid_positioning( Mcr, xMp, erp ); + +} diff --git a/libs/codec/gsm/src/short_term.c b/libs/codec/gsm/src/short_term.c new file mode 100644 index 0000000000..9398df1e26 --- /dev/null +++ b/libs/codec/gsm/src/short_term.c @@ -0,0 +1,448 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +#include +#include + +#include "private.h" + +#include "gsm.h" +#include "proto.h" +#ifdef K6OPT +#include "k6opt.h" + +#define Short_term_analysis_filtering Short_term_analysis_filteringx + +#endif +/* + * SHORT TERM ANALYSIS FILTERING SECTION + */ + +/* 4.2.8 */ + +static void Decoding_of_the_coded_Log_Area_Ratios P2((LARc,LARpp), + word * LARc, /* coded log area ratio [0..7] IN */ + word * LARpp) /* out: decoded .. */ +{ + register word temp1 /* , temp2 */; + + /* This procedure requires for efficient implementation + * two tables. + * + * INVA[1..8] = integer( (32768 * 8) / real_A[1..8]) + * MIC[1..8] = minimum value of the LARc[1..8] + */ + + /* Compute the LARpp[1..8] + */ + + /* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) { + * + * temp1 = GSM_ADD( *LARc, *MIC ) << 10; + * temp2 = *B << 1; + * temp1 = GSM_SUB( temp1, temp2 ); + * + * assert(*INVA != MIN_WORD); + * + * temp1 = GSM_MULT_R( *INVA, temp1 ); + * *LARpp = GSM_ADD( temp1, temp1 ); + * } + */ + +#undef STEP +#define STEP( B, MIC, INVA ) \ + temp1 = GSM_ADD( *LARc++, MIC ) << 10; \ + temp1 = GSM_SUB( temp1, B << 1 ); \ + temp1 = GSM_MULT_R( INVA, temp1 ); \ + *LARpp++ = GSM_ADD( temp1, temp1 ); + + STEP( 0, -32, 13107 ); + STEP( 0, -32, 13107 ); + STEP( 2048, -16, 13107 ); + STEP( -2560, -16, 13107 ); + + STEP( 94, -8, 19223 ); + STEP( -1792, -8, 17476 ); + STEP( -341, -4, 31454 ); + STEP( -1144, -4, 29708 ); + + /* NOTE: the addition of *MIC is used to restore + * the sign of *LARc. + */ +} + +/* 4.2.9 */ +/* Computation of the quantized reflection coefficients + */ + +/* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] + */ + +/* + * Within each frame of 160 analyzed speech samples the short term + * analysis and synthesis filters operate with four different sets of + * coefficients, derived from the previous set of decoded LARs(LARpp(j-1)) + * and the actual set of decoded LARs (LARpp(j)) + * + * (Initial value: LARpp(j-1)[1..8] = 0.) + */ + +static void Coefficients_0_12 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 )); + *LARp = GSM_ADD( *LARp, SASR( *LARpp_j_1, 1)); + } +} + +static void Coefficients_13_26 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 1), SASR( *LARpp_j, 1 )); + } +} + +static void Coefficients_27_39 P3((LARpp_j_1, LARpp_j, LARp), + register word * LARpp_j_1, + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { + *LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 )); + *LARp = GSM_ADD( *LARp, SASR( *LARpp_j, 1 )); + } +} + + +static void Coefficients_40_159 P2((LARpp_j, LARp), + register word * LARpp_j, + register word * LARp) +{ + register int i; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j++) + *LARp = *LARpp_j; +} + +/* 4.2.9.2 */ + +static void LARp_to_rp P1((LARp), + register word * LARp) /* [0..7] IN/OUT */ +/* + * The input of this procedure is the interpolated LARp[0..7] array. + * The reflection coefficients, rp[i], are used in the analysis + * filter and in the synthesis filter. + */ +{ + register int i; + register word temp; + + for (i = 1; i <= 8; i++, LARp++) { + + /* temp = GSM_ABS( *LARp ); + * + * if (temp < 11059) temp <<= 1; + * else if (temp < 20070) temp += 11059; + * else temp = GSM_ADD( temp >> 2, 26112 ); + * + * *LARp = *LARp < 0 ? -temp : temp; + */ + + if (*LARp < 0) { + temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp); + *LARp = - ((temp < 11059) ? temp << 1 + : ((temp < 20070) ? temp + 11059 + : GSM_ADD( temp >> 2, 26112 ))); + } else { + temp = *LARp; + *LARp = (temp < 11059) ? temp << 1 + : ((temp < 20070) ? temp + 11059 + : GSM_ADD( temp >> 2, 26112 )); + } + } +} + + +/* 4.2.10 */ +#ifndef Short_term_analysis_filtering + +/* SJB Remark: + * I tried 2 MMX versions of this function, neither is significantly + * faster than the C version which follows. MMX might be useful if + * one were processing 2 input streams in parallel. + */ +static void Short_term_analysis_filtering P4((u0,rp0,k_n,s), + register word * u0, + register word * rp0, /* [0..7] IN */ + register int k_n, /* k_end - k_start */ + register word * s /* [0..n-1] IN/OUT */ +) +/* + * This procedure computes the short term residual signal d[..] to be fed + * to the RPE-LTP loop from the s[..] signal and from the local rp[..] + * array (quantized reflection coefficients). As the call of this + * procedure can be done in many ways (see the interpolation of the LAR + * coefficient), it is assumed that the computation begins with index + * k_start (for arrays d[..] and s[..]) and stops with index k_end + * (k_start and k_end are defined in 4.2.9.1). This procedure also + * needs to keep the array u0[0..7] in memory for each call. + */ +{ + register word * u_top = u0 + 8; + register word * s_top = s + k_n; + + while (s < s_top) { + register word *u, *rp ; + register longword di, u_out; + di = u_out = *s; + for (rp=rp0, u=u0; u>15); + di = di + (((rpi*ui)+0x4000)>>15); + /* make the common case fastest: */ + if ((u_out == (word)u_out) && (di == (word)di)) continue; + /* otherwise do slower fixup (saturation) */ + if (u_out>MAX_WORD) u_out=MAX_WORD; + else if (u_outMAX_WORD) di=MAX_WORD; + else if (div; + register int i; + register longword sri; + + while (k--) { + sri = *wt++; + for (i = 8; i--;) { + register longword tmp1, tmp2; + + /* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) ); + */ + tmp1 = rrp[i]; + tmp2 = v[i]; + + tmp2 = (( tmp1 * tmp2 + 16384) >> 15) ; + /* saturation done below */ + sri -= tmp2; + if (sri != (word)sri) { + sri = (sri<0)? MIN_WORD:MAX_WORD; + } + /* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) ); + */ + + tmp1 = (( tmp1 * sri + 16384) >> 15) ; + /* saturation done below */ + tmp1 += v[i]; + if (tmp1 != (word)tmp1) { + tmp1 = (tmp1<0)? MIN_WORD:MAX_WORD; + } + v[i+1] = tmp1; + } + *sr++ = v[0] = sri; + } +} + + +#if defined(FAST) && defined(USE_FLOAT_MUL) + +static void Fast_Short_term_synthesis_filtering P5((S,rrp,k,wt,sr), + struct gsm_state * S, + register word * rrp, /* [0..7] IN */ + register int k, /* k_end - k_start */ + register word * wt, /* [0..k-1] IN */ + register word * sr /* [0..k-1] OUT */ +) +{ + register word * v = S->v; + register int i; + + float va[9], rrpa[8]; + register float scalef = 3.0517578125e-5, temp; + + for (i = 0; i < 8; ++i) { + va[i] = v[i]; + rrpa[i] = (float)rrp[i] * scalef; + } + while (k--) { + register float sri = *wt++; + for (i = 8; i--;) { + sri -= rrpa[i] * va[i]; + if (sri < -32768.) sri = -32768.; + else if (sri > 32767.) sri = 32767.; + + temp = va[i] + rrpa[i] * sri; + if (temp < -32768.) temp = -32768.; + else if (temp > 32767.) temp = 32767.; + va[i+1] = temp; + } + *sr++ = va[0] = sri; + } + for (i = 0; i < 9; ++i) v[i] = va[i]; +} + +#endif /* defined(FAST) && defined(USE_FLOAT_MUL) */ + +void Gsm_Short_Term_Analysis_Filter P3((S,LARc,s), + + struct gsm_state * S, + + word * LARc, /* coded log area ratio [0..7] IN */ + word * s /* signal [0..159] IN/OUT */ +) +{ + word * LARpp_j = S->LARpp[ S->j ]; + word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ]; + + word LARp[8]; +int i; +#undef FILTER +#if defined(FAST) && defined(USE_FLOAT_MUL) +# define FILTER (* (S->fast \ + ? Fast_Short_term_analysis_filtering \ + : Short_term_analysis_filtering )) + +#else +# define FILTER Short_term_analysis_filtering +#endif + + Decoding_of_the_coded_Log_Area_Ratios( LARc, LARpp_j ); + + Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER( S->u, LARp, 13, s); + + Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S->u, LARp, 14, s + 13); + + Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S->u, LARp, 13, s + 27); + + Coefficients_40_159( LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S->u, LARp, 120, s + 40); + +} + +void Gsm_Short_Term_Synthesis_Filter P4((S, LARcr, wt, s), + struct gsm_state * S, + + word * LARcr, /* received log area ratios [0..7] IN */ + word * wt, /* received d [0..159] IN */ + + word * s /* signal s [0..159] OUT */ +) +{ + word * LARpp_j = S->LARpp[ S->j ]; + word * LARpp_j_1 = S->LARpp[ S->j ^=1 ]; + + word LARp[8]; + +#undef FILTER +#if defined(FAST) && defined(USE_FLOAT_MUL) + +# define FILTER (* (S->fast \ + ? Fast_Short_term_synthesis_filtering \ + : Short_term_synthesis_filtering )) +#else +# define FILTER Short_term_synthesis_filtering +#endif + + Decoding_of_the_coded_Log_Area_Ratios( LARcr, LARpp_j ); + + Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, wt, s ); + + Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 14, wt + 13, s + 13 ); + + Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); + LARp_to_rp( LARp ); + FILTER( S, LARp, 13, wt + 27, s + 27 ); + + Coefficients_40_159( LARpp_j, LARp ); + LARp_to_rp( LARp ); + FILTER(S, LARp, 120, wt + 40, s + 40); +} diff --git a/libs/codec/gsm/src/table.c b/libs/codec/gsm/src/table.c new file mode 100644 index 0000000000..bdca9fa4d0 --- /dev/null +++ b/libs/codec/gsm/src/table.c @@ -0,0 +1,63 @@ +/* + * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische + * Universitaet Berlin. See the accompanying file "COPYRIGHT" for + * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. + */ + +/* $Header$ */ + +/* Most of these tables are inlined at their point of use. + */ + +/* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP + * CODER AND DECODER + * + * (Most of them inlined, so watch out.) + */ + +#define GSM_TABLE_C +#include "private.h" +#include "gsm.h" + +/* Table 4.1 Quantization of the Log.-Area Ratios + */ +/* i 1 2 3 4 5 6 7 8 */ +word gsm_A[8] = {20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036}; +word gsm_B[8] = { 0, 0, 2048, -2560, 94, -1792, -341, -1144}; +word gsm_MIC[8] = { -32, -32, -16, -16, -8, -8, -4, -4 }; +word gsm_MAC[8] = { 31, 31, 15, 15, 7, 7, 3, 3 }; + + +/* Table 4.2 Tabulation of 1/A[1..8] + */ +word gsm_INVA[8]={ 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 }; + + +/* Table 4.3a Decision level of the LTP gain quantizer + */ +/* bc 0 1 2 3 */ +word gsm_DLB[4] = { 6554, 16384, 26214, 32767 }; + + +/* Table 4.3b Quantization levels of the LTP gain quantizer + */ +/* bc 0 1 2 3 */ +word gsm_QLB[4] = { 3277, 11469, 21299, 32767 }; + + +/* Table 4.4 Coefficients of the weighting filter + */ +/* i 0 1 2 3 4 5 6 7 8 9 10 */ +word gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 }; + + +/* Table 4.5 Normalized inverse mantissa used to compute xM/xmax + */ +/* i 0 1 2 3 4 5 6 7 */ +word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 }; + + +/* Table 4.6 Normalized direct mantissa used to compute xM/xmax + */ +/* i 0 1 2 3 4 5 6 7 */ +word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 }; diff --git a/libs/codec/ilbc/FrameClassify.c b/libs/codec/ilbc/FrameClassify.c new file mode 100644 index 0000000000..9a6f029369 --- /dev/null +++ b/libs/codec/ilbc/FrameClassify.c @@ -0,0 +1,110 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + FrameClassify.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include "iLBC_define.h" +#include "FrameClassify.h" + +/*---------------------------------------------------------------* + * Classification of subframes to localize start state + *--------------------------------------------------------------*/ + +int FrameClassify( /* index to the max-energy sub-frame */ + iLBC_Enc_Inst_t *iLBCenc_inst, + /* (i/o) the encoder state structure */ + float *residual /* (i) lpc residual signal */ +) { + float max_ssqEn, fssqEn[NSUB_MAX], bssqEn[NSUB_MAX], *pp; + int n, l, max_ssqEn_n; + const float ssqEn_win[NSUB_MAX-1]={(float)0.8,(float)0.9, + (float)1.0,(float)0.9,(float)0.8}; + const float sampEn_win[5]={(float)1.0/(float)6.0, + (float)2.0/(float)6.0, (float)3.0/(float)6.0, + (float)4.0/(float)6.0, (float)5.0/(float)6.0}; + + /* init the front and back energies to zero */ + + memset(fssqEn, 0, NSUB_MAX*sizeof(float)); + memset(bssqEn, 0, NSUB_MAX*sizeof(float)); + + /* Calculate front of first seqence */ + + n=0; + pp=residual; + + + for (l=0; l<5; l++) { + fssqEn[n] += sampEn_win[l] * (*pp) * (*pp); + pp++; + } + for (l=5; lnsub-1; n++) { + pp=residual+n*SUBL; + for (l=0; l<5; l++) { + fssqEn[n] += sampEn_win[l] * (*pp) * (*pp); + bssqEn[n] += (*pp) * (*pp); + pp++; + } + for (l=5; lnsub-1; + pp=residual+n*SUBL; + for (l=0; lmode==20) l=1; + else l=0; + + max_ssqEn=(fssqEn[0]+bssqEn[1])*ssqEn_win[l]; + max_ssqEn_n=1; + for (n=2; nnsub; n++) { + + l++; + + + if ((fssqEn[n-1]+bssqEn[n])*ssqEn_win[l] > max_ssqEn) { + max_ssqEn=(fssqEn[n-1]+bssqEn[n]) * + ssqEn_win[l]; + max_ssqEn_n=n; + } + } + + return max_ssqEn_n; +} + + diff --git a/libs/codec/ilbc/FrameClassify.h b/libs/codec/ilbc/FrameClassify.h new file mode 100644 index 0000000000..6b583703ab --- /dev/null +++ b/libs/codec/ilbc/FrameClassify.h @@ -0,0 +1,26 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + FrameClassify.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + + + +#ifndef __iLBC_FRAMECLASSIFY_H +#define __iLBC_FRAMECLASSIFY_H + +int FrameClassify( /* index to the max-energy sub-frame */ + iLBC_Enc_Inst_t *iLBCenc_inst, + /* (i/o) the encoder state structure */ + float *residual /* (i) lpc residual signal */ +); + +#endif + + diff --git a/libs/codec/ilbc/LPCdecode.c b/libs/codec/ilbc/LPCdecode.c new file mode 100644 index 0000000000..741c731c41 --- /dev/null +++ b/libs/codec/ilbc/LPCdecode.c @@ -0,0 +1,152 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + LPC_decode.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include +#include + +#include "helpfun.h" +#include "lsf.h" +#include "iLBC_define.h" +#include "LPCdecode.h" +#include "constants.h" + +/*---------------------------------------------------------------* + * interpolation of lsf coefficients for the decoder + *--------------------------------------------------------------*/ + +void LSFinterpolate2a_dec( + float *a, /* (o) lpc coefficients for a sub-frame */ + float *lsf1, /* (i) first lsf coefficient vector */ + + + float *lsf2, /* (i) second lsf coefficient vector */ + float coef, /* (i) interpolation weight */ + int length /* (i) length of lsf vectors */ +){ + float lsftmp[LPC_FILTERORDER]; + + interpolate(lsftmp, lsf1, lsf2, coef, length); + lsf2a(a, lsftmp); +} + +/*---------------------------------------------------------------* + * obtain dequantized lsf coefficients from quantization index + *--------------------------------------------------------------*/ + +void SimplelsfDEQ( + float *lsfdeq, /* (o) dequantized lsf coefficients */ + int *index, /* (i) quantization index */ + int lpc_n /* (i) number of LPCs */ +){ + int i, j, pos, cb_pos; + + /* decode first LSF */ + + pos = 0; + cb_pos = 0; + for (i = 0; i < LSF_NSPLIT; i++) { + for (j = 0; j < dim_lsfCbTbl[i]; j++) { + lsfdeq[pos + j] = lsfCbTbl[cb_pos + + (long)(index[i])*dim_lsfCbTbl[i] + j]; + } + pos += dim_lsfCbTbl[i]; + cb_pos += size_lsfCbTbl[i]*dim_lsfCbTbl[i]; + } + + if (lpc_n>1) { + + /* decode last LSF */ + + pos = 0; + cb_pos = 0; + for (i = 0; i < LSF_NSPLIT; i++) { + for (j = 0; j < dim_lsfCbTbl[i]; j++) { + lsfdeq[LPC_FILTERORDER + pos + j] = + lsfCbTbl[cb_pos + + (long)(index[LSF_NSPLIT + i])* + dim_lsfCbTbl[i] + j]; + } + pos += dim_lsfCbTbl[i]; + cb_pos += size_lsfCbTbl[i]*dim_lsfCbTbl[i]; + } + } +} + +/*----------------------------------------------------------------* + + + * obtain synthesis and weighting filters form lsf coefficients + *---------------------------------------------------------------*/ + +void DecoderInterpolateLSF( + float *syntdenum, /* (o) synthesis filter coefficients */ + float *weightdenum, /* (o) weighting denumerator + coefficients */ + float *lsfdeq, /* (i) dequantized lsf coefficients */ + int length, /* (i) length of lsf coefficient vector */ + iLBC_Dec_Inst_t *iLBCdec_inst + /* (i) the decoder state structure */ +){ + int i, pos, lp_length; + float lp[LPC_FILTERORDER + 1], *lsfdeq2; + + lsfdeq2 = lsfdeq + length; + lp_length = length + 1; + + if (iLBCdec_inst->mode==30) { + /* sub-frame 1: Interpolation between old and first */ + + LSFinterpolate2a_dec(lp, iLBCdec_inst->lsfdeqold, lsfdeq, + lsf_weightTbl_30ms[0], length); + memcpy(syntdenum,lp,lp_length*sizeof(float)); + bwexpand(weightdenum, lp, LPC_CHIRP_WEIGHTDENUM, + lp_length); + + /* sub-frames 2 to 6: interpolation between first + and last LSF */ + + pos = lp_length; + for (i = 1; i < 6; i++) { + LSFinterpolate2a_dec(lp, lsfdeq, lsfdeq2, + lsf_weightTbl_30ms[i], length); + memcpy(syntdenum + pos,lp,lp_length*sizeof(float)); + bwexpand(weightdenum + pos, lp, + LPC_CHIRP_WEIGHTDENUM, lp_length); + pos += lp_length; + } + } + else { + pos = 0; + for (i = 0; i < iLBCdec_inst->nsub; i++) { + LSFinterpolate2a_dec(lp, iLBCdec_inst->lsfdeqold, + lsfdeq, lsf_weightTbl_20ms[i], length); + memcpy(syntdenum+pos,lp,lp_length*sizeof(float)); + bwexpand(weightdenum+pos, lp, LPC_CHIRP_WEIGHTDENUM, + lp_length); + pos += lp_length; + } + } + + /* update memory */ + + + + if (iLBCdec_inst->mode==30) + memcpy(iLBCdec_inst->lsfdeqold, lsfdeq2, + length*sizeof(float)); + else + memcpy(iLBCdec_inst->lsfdeqold, lsfdeq, + length*sizeof(float)); + +} + + diff --git a/libs/codec/ilbc/LPCdecode.h b/libs/codec/ilbc/LPCdecode.h new file mode 100644 index 0000000000..84116e08f2 --- /dev/null +++ b/libs/codec/ilbc/LPCdecode.h @@ -0,0 +1,44 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + LPC_decode.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#ifndef __iLBC_LPC_DECODE_H +#define __iLBC_LPC_DECODE_H + +void LSFinterpolate2a_dec( + + + float *a, /* (o) lpc coefficients for a sub-frame */ + float *lsf1, /* (i) first lsf coefficient vector */ + float *lsf2, /* (i) second lsf coefficient vector */ + float coef, /* (i) interpolation weight */ + int length /* (i) length of lsf vectors */ +); + +void SimplelsfDEQ( + float *lsfdeq, /* (o) dequantized lsf coefficients */ + int *index, /* (i) quantization index */ + int lpc_n /* (i) number of LPCs */ +); + +void DecoderInterpolateLSF( + float *syntdenum, /* (o) synthesis filter coefficients */ + float *weightdenum, /* (o) weighting denumerator + coefficients */ + float *lsfdeq, /* (i) dequantized lsf coefficients */ + int length, /* (i) length of lsf coefficient vector */ + iLBC_Dec_Inst_t *iLBCdec_inst + /* (i) the decoder state structure */ +); + +#endif + + diff --git a/libs/codec/ilbc/LPCencode.c b/libs/codec/ilbc/LPCencode.c new file mode 100644 index 0000000000..d1286e2199 --- /dev/null +++ b/libs/codec/ilbc/LPCencode.c @@ -0,0 +1,228 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + LPCencode.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include + + + +#include "iLBC_define.h" +#include "LPCencode.h" +#include "helpfun.h" +#include "lsf.h" +#include "constants.h" + +/*----------------------------------------------------------------* + * lpc analysis (subrutine to LPCencode) + *---------------------------------------------------------------*/ + +static void SimpleAnalysis( + float *lsf, /* (o) lsf coefficients */ + float *data, /* (i) new data vector */ + iLBC_Enc_Inst_t *iLBCenc_inst + /* (i/o) the encoder state structure */ +){ + int k, is; + float temp[BLOCKL_MAX], lp[LPC_FILTERORDER + 1]; + float lp2[LPC_FILTERORDER + 1]; + float r[LPC_FILTERORDER + 1]; + + is=LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl; + memcpy(iLBCenc_inst->lpc_buffer+is,data, + iLBCenc_inst->blockl*sizeof(float)); + + /* No lookahead, last window is asymmetric */ + + for (k = 0; k < iLBCenc_inst->lpc_n; k++) { + + is = LPC_LOOKBACK; + + if (k < (iLBCenc_inst->lpc_n - 1)) { + window(temp, lpc_winTbl, + iLBCenc_inst->lpc_buffer, BLOCKL_MAX); + } else { + window(temp, lpc_asymwinTbl, + iLBCenc_inst->lpc_buffer + is, BLOCKL_MAX); + } + + autocorr(r, temp, BLOCKL_MAX, LPC_FILTERORDER); + window(r, r, lpc_lagwinTbl, LPC_FILTERORDER + 1); + + levdurb(lp, temp, r, LPC_FILTERORDER); + bwexpand(lp2, lp, LPC_CHIRP_SYNTDENUM, LPC_FILTERORDER+1); + + a2lsf(lsf + k*LPC_FILTERORDER, lp2); + } + is=LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl; + memmove(iLBCenc_inst->lpc_buffer, + iLBCenc_inst->lpc_buffer+LPC_LOOKBACK+BLOCKL_MAX-is, + is*sizeof(float)); +} + +/*----------------------------------------------------------------* + + + * lsf interpolator and conversion from lsf to a coefficients + * (subrutine to SimpleInterpolateLSF) + *---------------------------------------------------------------*/ + +static void LSFinterpolate2a_enc( + float *a, /* (o) lpc coefficients */ + float *lsf1,/* (i) first set of lsf coefficients */ + float *lsf2,/* (i) second set of lsf coefficients */ + float coef, /* (i) weighting coefficient to use between + lsf1 and lsf2 */ + long length /* (i) length of coefficient vectors */ +){ + float lsftmp[LPC_FILTERORDER]; + + interpolate(lsftmp, lsf1, lsf2, coef, length); + lsf2a(a, lsftmp); +} + +/*----------------------------------------------------------------* + * lsf interpolator (subrutine to LPCencode) + *---------------------------------------------------------------*/ + +static void SimpleInterpolateLSF( + float *syntdenum, /* (o) the synthesis filter denominator + resulting from the quantized + interpolated lsf */ + float *weightdenum, /* (o) the weighting filter denominator + resulting from the unquantized + interpolated lsf */ + float *lsf, /* (i) the unquantized lsf coefficients */ + float *lsfdeq, /* (i) the dequantized lsf coefficients */ + float *lsfold, /* (i) the unquantized lsf coefficients of + the previous signal frame */ + float *lsfdeqold, /* (i) the dequantized lsf coefficients of + the previous signal frame */ + int length, /* (i) should equate LPC_FILTERORDER */ + iLBC_Enc_Inst_t *iLBCenc_inst + /* (i/o) the encoder state structure */ +){ + int i, pos, lp_length; + float lp[LPC_FILTERORDER + 1], *lsf2, *lsfdeq2; + + lsf2 = lsf + length; + lsfdeq2 = lsfdeq + length; + lp_length = length + 1; + + if (iLBCenc_inst->mode==30) { + /* sub-frame 1: Interpolation between old and first + set of lsf coefficients */ + + LSFinterpolate2a_enc(lp, lsfdeqold, lsfdeq, + lsf_weightTbl_30ms[0], length); + memcpy(syntdenum,lp,lp_length*sizeof(float)); + LSFinterpolate2a_enc(lp, lsfold, lsf, + + + lsf_weightTbl_30ms[0], length); + bwexpand(weightdenum, lp, LPC_CHIRP_WEIGHTDENUM, lp_length); + + /* sub-frame 2 to 6: Interpolation between first + and second set of lsf coefficients */ + + pos = lp_length; + for (i = 1; i < iLBCenc_inst->nsub; i++) { + LSFinterpolate2a_enc(lp, lsfdeq, lsfdeq2, + lsf_weightTbl_30ms[i], length); + memcpy(syntdenum + pos,lp,lp_length*sizeof(float)); + + LSFinterpolate2a_enc(lp, lsf, lsf2, + lsf_weightTbl_30ms[i], length); + bwexpand(weightdenum + pos, lp, + LPC_CHIRP_WEIGHTDENUM, lp_length); + pos += lp_length; + } + } + else { + pos = 0; + for (i = 0; i < iLBCenc_inst->nsub; i++) { + LSFinterpolate2a_enc(lp, lsfdeqold, lsfdeq, + lsf_weightTbl_20ms[i], length); + memcpy(syntdenum+pos,lp,lp_length*sizeof(float)); + LSFinterpolate2a_enc(lp, lsfold, lsf, + lsf_weightTbl_20ms[i], length); + bwexpand(weightdenum+pos, lp, + LPC_CHIRP_WEIGHTDENUM, lp_length); + pos += lp_length; + } + } + + /* update memory */ + + if (iLBCenc_inst->mode==30) { + memcpy(lsfold, lsf2, length*sizeof(float)); + memcpy(lsfdeqold, lsfdeq2, length*sizeof(float)); + } + else { + memcpy(lsfold, lsf, length*sizeof(float)); + memcpy(lsfdeqold, lsfdeq, length*sizeof(float)); + } +} + +/*----------------------------------------------------------------* + * lsf quantizer (subrutine to LPCencode) + *---------------------------------------------------------------*/ + +static void SimplelsfQ( + float *lsfdeq, /* (o) dequantized lsf coefficients + (dimension FILTERORDER) */ + int *index, /* (o) quantization index */ + float *lsf, /* (i) the lsf coefficient vector to be + + + quantized (dimension FILTERORDER ) */ + int lpc_n /* (i) number of lsf sets to quantize */ +){ + /* Quantize first LSF with memoryless split VQ */ + SplitVQ(lsfdeq, index, lsf, lsfCbTbl, LSF_NSPLIT, + dim_lsfCbTbl, size_lsfCbTbl); + + if (lpc_n==2) { + /* Quantize second LSF with memoryless split VQ */ + SplitVQ(lsfdeq + LPC_FILTERORDER, index + LSF_NSPLIT, + lsf + LPC_FILTERORDER, lsfCbTbl, LSF_NSPLIT, + dim_lsfCbTbl, size_lsfCbTbl); + } +} + +/*----------------------------------------------------------------* + * lpc encoder + *---------------------------------------------------------------*/ + +void LPCencode( + float *syntdenum, /* (i/o) synthesis filter coefficients + before/after encoding */ + float *weightdenum, /* (i/o) weighting denumerator + coefficients before/after + encoding */ + int *lsf_index, /* (o) lsf quantization index */ + float *data, /* (i) lsf coefficients to quantize */ + iLBC_Enc_Inst_t *iLBCenc_inst + /* (i/o) the encoder state structure */ +){ + float lsf[LPC_FILTERORDER * LPC_N_MAX]; + float lsfdeq[LPC_FILTERORDER * LPC_N_MAX]; + int change=0; + + SimpleAnalysis(lsf, data, iLBCenc_inst); + SimplelsfQ(lsfdeq, lsf_index, lsf, iLBCenc_inst->lpc_n); + change=LSF_check(lsfdeq, LPC_FILTERORDER, iLBCenc_inst->lpc_n); + SimpleInterpolateLSF(syntdenum, weightdenum, + lsf, lsfdeq, iLBCenc_inst->lsfold, + iLBCenc_inst->lsfdeqold, LPC_FILTERORDER, iLBCenc_inst); +} + + + diff --git a/libs/codec/ilbc/LPCencode.h b/libs/codec/ilbc/LPCencode.h new file mode 100644 index 0000000000..464282e629 --- /dev/null +++ b/libs/codec/ilbc/LPCencode.h @@ -0,0 +1,29 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + LPCencode.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#ifndef __iLBC_LPCENCOD_H +#define __iLBC_LPCENCOD_H + +void LPCencode( + float *syntdenum, /* (i/o) synthesis filter coefficients + before/after encoding */ + float *weightdenum, /* (i/o) weighting denumerator coefficients + before/after encoding */ + int *lsf_index, /* (o) lsf quantization index */ + float *data, /* (i) lsf coefficients to quantize */ + iLBC_Enc_Inst_t *iLBCenc_inst + /* (i/o) the encoder state structure */ +); + +#endif + + diff --git a/libs/codec/ilbc/Makefile b/libs/codec/ilbc/Makefile new file mode 100644 index 0000000000..5ef581ebe7 --- /dev/null +++ b/libs/codec/ilbc/Makefile @@ -0,0 +1,25 @@ +ARCH=$(PROC) +CFLAGS+=-Wall -O3 -funroll-loops +ifneq (${OSARCH},CYGWIN) +CFLAGS += -fPIC +endif +LIB=libilbc.a + +OBJS= anaFilter.o iCBSearch.o packing.o \ + constants.o gainquant.o iLBC_decode.o StateConstructW.o \ + createCB.o getCBvec.o iLBC_encode.o StateSearchW.o doCPLC.o \ + helpfun.o syntFilter.o enhancer.o hpInput.o LPCdecode.o \ + filter.o hpOutput.o LPCencode.o FrameClassify.o iCBConstruct.o lsf.o + +all: $(LIB) + + +$(LIB): $(OBJS) + ar cr $(LIB) $(OBJS) + ranlib $(LIB) + +clean: + rm -f $(LIB) *.o + +install: + diff --git a/libs/codec/ilbc/StateConstructW.c b/libs/codec/ilbc/StateConstructW.c new file mode 100644 index 0000000000..31d997dfe4 --- /dev/null +++ b/libs/codec/ilbc/StateConstructW.c @@ -0,0 +1,76 @@ + +/****************************************************************** + + + + iLBC Speech Coder ANSI-C Source Code + + StateConstructW.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include +#include + +#include "iLBC_define.h" +#include "StateConstructW.h" +#include "constants.h" +#include "filter.h" + +/*----------------------------------------------------------------* + * decoding of the start state + *---------------------------------------------------------------*/ + +void StateConstructW( + int idxForMax, /* (i) 6-bit index for the quantization of + max amplitude */ + int *idxVec, /* (i) vector of quantization indexes */ + float *syntDenum, /* (i) synthesis filter denumerator */ + float *out, /* (o) the decoded state vector */ + int len /* (i) length of a state vector */ +){ + float maxVal, tmpbuf[LPC_FILTERORDER+2*STATE_LEN], *tmp, + numerator[LPC_FILTERORDER+1]; + float foutbuf[LPC_FILTERORDER+2*STATE_LEN], *fout; + int k,tmpi; + + /* decoding of the maximum value */ + + maxVal = state_frgqTbl[idxForMax]; + maxVal = (float)pow(10,maxVal)/(float)4.5; + + /* initialization of buffers and coefficients */ + + memset(tmpbuf, 0, LPC_FILTERORDER*sizeof(float)); + memset(foutbuf, 0, LPC_FILTERORDER*sizeof(float)); + for (k=0; k +#include + +#include "iLBC_define.h" +#include "StateSearchW.h" +#include "constants.h" +#include "filter.h" +#include "helpfun.h" + +/*----------------------------------------------------------------* + * predictive noise shaping encoding of scaled start state + * (subrutine for StateSearchW) + *---------------------------------------------------------------*/ + +void AbsQuantW( + iLBC_Enc_Inst_t *iLBCenc_inst, + /* (i) Encoder instance */ + float *in, /* (i) vector to encode */ + float *syntDenum, /* (i) denominator of synthesis filter */ + float *weightDenum, /* (i) denominator of weighting filter */ + int *out, /* (o) vector of quantizer indexes */ + int len, /* (i) length of vector to encode and + vector of quantizer indexes */ + int state_first /* (i) position of start state in the + 80 vec */ +){ + float *syntOut; + float syntOutBuf[LPC_FILTERORDER+STATE_SHORT_LEN_30MS]; + float toQ, xq; + int n; + int index; + + /* initialization of buffer for filtering */ + + memset(syntOutBuf, 0, LPC_FILTERORDER*sizeof(float)); + + + + /* initialization of pointer for filtering */ + + syntOut = &syntOutBuf[LPC_FILTERORDER]; + + /* synthesis and weighting filters on input */ + + if (state_first) { + AllPoleFilter (in, weightDenum, SUBL, LPC_FILTERORDER); + } else { + AllPoleFilter (in, weightDenum, + iLBCenc_inst->state_short_len-SUBL, + LPC_FILTERORDER); + } + + /* encoding loop */ + + for (n=0; nstate_short_len-SUBL))) { + syntDenum += (LPC_FILTERORDER+1); + weightDenum += (LPC_FILTERORDER+1); + + /* synthesis and weighting filters on input */ + AllPoleFilter (&in[n], weightDenum, len-n, + LPC_FILTERORDER); + + } + + /* prediction of synthesized and weighted input */ + + syntOut[n] = 0.0; + AllPoleFilter (&syntOut[n], weightDenum, 1, + LPC_FILTERORDER); + + /* quantization */ + + toQ = in[n]-syntOut[n]; + sort_sq(&xq, &index, toQ, state_sq3Tbl, 8); + out[n]=index; + syntOut[n] = state_sq3Tbl[out[n]]; + + /* update of the prediction filter */ + + + + AllPoleFilter(&syntOut[n], weightDenum, 1, + LPC_FILTERORDER); + } +} + +/*----------------------------------------------------------------* + * encoding of start state + *---------------------------------------------------------------*/ + +void StateSearchW( + iLBC_Enc_Inst_t *iLBCenc_inst, + /* (i) Encoder instance */ + float *residual,/* (i) target residual vector */ + float *syntDenum, /* (i) lpc synthesis filter */ + float *weightDenum, /* (i) weighting filter denuminator */ + int *idxForMax, /* (o) quantizer index for maximum + amplitude */ + int *idxVec, /* (o) vector of quantization indexes */ + int len, /* (i) length of all vectors */ + int state_first /* (i) position of start state in the + 80 vec */ +){ + float dtmp, maxVal; + float tmpbuf[LPC_FILTERORDER+2*STATE_SHORT_LEN_30MS]; + float *tmp, numerator[1+LPC_FILTERORDER]; + float foutbuf[LPC_FILTERORDER+2*STATE_SHORT_LEN_30MS], *fout; + int k; + float qmax, scal; + + /* initialization of buffers and filter coefficients */ + + memset(tmpbuf, 0, LPC_FILTERORDER*sizeof(float)); + memset(foutbuf, 0, LPC_FILTERORDER*sizeof(float)); + for (k=0; k maxVal*maxVal){ + maxVal = fout[k]; + } + } + maxVal=(float)fabs(maxVal); + + /* encoding of the maximum amplitude value */ + + if (maxVal < 10.0) { + maxVal = 10.0; + } + maxVal = (float)log10(maxVal); + sort_sq(&dtmp, idxForMax, maxVal, state_frgqTbl, 64); + + /* decoding of the maximum amplitude representation value, + and corresponding scaling of start state */ + + maxVal=state_frgqTbl[*idxForMax]; + qmax = (float)pow(10,maxVal); + scal = (float)(4.5)/qmax; + for (k=0; k +#include "anaFilter.h" +#include "iLBC_define.h" + +/*----------------------------------------------------------------* + * LP analysis filter. + + + *---------------------------------------------------------------*/ + +void anaFilter( + float *In, /* (i) Signal to be filtered */ + float *a, /* (i) LP parameters */ + int len,/* (i) Length of signal */ + float *Out, /* (o) Filtered signal */ + float *mem /* (i/o) Filter state */ +){ + int i, j; + float *po, *pi, *pm, *pa; + + po = Out; + + /* Filter first part using memory from past */ + + for (i=0; i +#include + +/*----------------------------------------------------------------* + * Construct an additional codebook vector by filtering the + * initial codebook buffer. This vector is then used to expand + * the codebook with an additional section. + *---------------------------------------------------------------*/ + +void filteredCBvecs( + float *cbvectors, /* (o) Codebook vectors for the + higher section */ + float *mem, /* (i) Buffer to create codebook + vector from */ + int lMem /* (i) Length of buffer */ +){ + int j, k; + float *pp, *pp1; + float tempbuff2[CB_MEML+CB_FILTERLEN]; + float *pos; + + memset(tempbuff2, 0, (CB_HALFFILTERLEN-1)*sizeof(float)); + memcpy(&tempbuff2[CB_HALFFILTERLEN-1], mem, lMem*sizeof(float)); + memset(&tempbuff2[lMem+CB_HALFFILTERLEN-1], 0, + (CB_HALFFILTERLEN+1)*sizeof(float)); + + /* Create codebook vector for higher section by filtering */ + + /* do filtering */ + pos=cbvectors; + memset(pos, 0, lMem*sizeof(float)); + for (k=0; k0.0) { + invenergy[tmpIndex]=(float)1.0/(energy[tmpIndex]+EPS); + } else { + invenergy[tmpIndex] = (float) 0.0; + } + + if (stage==0) { + measure = (float)-10000000.0; + + if (crossDot > 0.0) { + measure = crossDot*crossDot*invenergy[tmpIndex]; + } + } + else { + measure = crossDot*crossDot*invenergy[tmpIndex]; + } + + /* check if measure is better */ + ftmp = crossDot*invenergy[tmpIndex]; + + if ((measure>*max_measure) && (fabs(ftmp) +#include +#include + +#include "iLBC_define.h" +#include "doCPLC.h" + +/*----------------------------------------------------------------* + * Compute cross correlation and pitch gain for pitch prediction + * of last subframe at given lag. + *---------------------------------------------------------------*/ + +static void compCorr( + float *cc, /* (o) cross correlation coefficient */ + float *gc, /* (o) gain */ + float *pm, + float *buffer, /* (i) signal buffer */ + int lag, /* (i) pitch lag */ + int bLen, /* (i) length of buffer */ + int sRange /* (i) correlation search length */ +){ + + + int i; + float ftmp1, ftmp2, ftmp3; + + /* Guard against getting outside buffer */ + if ((bLen-sRange-lag)<0) { + sRange=bLen-lag; + } + + ftmp1 = 0.0; + ftmp2 = 0.0; + ftmp3 = 0.0; + for (i=0; i 0.0) { + *cc = ftmp1*ftmp1/ftmp2; + *gc = (float)fabs(ftmp1/ftmp2); + *pm=(float)fabs(ftmp1)/ + ((float)sqrt(ftmp2)*(float)sqrt(ftmp3)); + } + else { + *cc = 0.0; + *gc = 0.0; + *pm=0.0; + } +} + +/*----------------------------------------------------------------* + * Packet loss concealment routine. Conceals a residual signal + * and LP parameters. If no packet loss, update state. + *---------------------------------------------------------------*/ + +void doThePLC( + float *PLCresidual, /* (o) concealed residual */ + float *PLClpc, /* (o) concealed LP parameters */ + int PLI, /* (i) packet loss indicator + 0 - no PL, 1 = PL */ + float *decresidual, /* (i) decoded residual */ + float *lpc, /* (i) decoded LPC (only used for no PL) */ + int inlag, /* (i) pitch lag */ + iLBC_Dec_Inst_t *iLBCdec_inst + /* (i/o) decoder instance */ +){ + int lag=20, randlag; + float gain, maxcc; + float use_gain; + float gain_comp, maxcc_comp, per, max_per; + int i, pick, use_lag; + + + float ftmp, randvec[BLOCKL_MAX], pitchfact, energy; + + /* Packet Loss */ + + if (PLI == 1) { + + iLBCdec_inst->consPLICount += 1; + + /* if previous frame not lost, + determine pitch pred. gain */ + + if (iLBCdec_inst->prevPLI != 1) { + + /* Search around the previous lag to find the + best pitch period */ + + lag=inlag-3; + compCorr(&maxcc, &gain, &max_per, + iLBCdec_inst->prevResidual, + lag, iLBCdec_inst->blockl, 60); + for (i=inlag-2;i<=inlag+3;i++) { + compCorr(&maxcc_comp, &gain_comp, &per, + iLBCdec_inst->prevResidual, + i, iLBCdec_inst->blockl, 60); + + if (maxcc_comp>maxcc) { + maxcc=maxcc_comp; + gain=gain_comp; + lag=i; + max_per=per; + } + } + + } + + /* previous frame lost, use recorded lag and periodicity */ + + else { + lag=iLBCdec_inst->prevLag; + max_per=iLBCdec_inst->per; + } + + /* downscaling */ + + use_gain=1.0; + if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320) + use_gain=(float)0.9; + else if (iLBCdec_inst->consPLICount* + iLBCdec_inst->blockl>2*320) + use_gain=(float)0.7; + else if (iLBCdec_inst->consPLICount* + iLBCdec_inst->blockl>3*320) + use_gain=(float)0.5; + else if (iLBCdec_inst->consPLICount* + + + iLBCdec_inst->blockl>4*320) + use_gain=(float)0.0; + + /* mix noise and pitch repeatition */ + ftmp=(float)sqrt(max_per); + if (ftmp>(float)0.7) + pitchfact=(float)1.0; + else if (ftmp>(float)0.4) + pitchfact=(ftmp-(float)0.4)/((float)0.7-(float)0.4); + else + pitchfact=0.0; + + + /* avoid repetition of same pitch cycle */ + use_lag=lag; + if (lag<80) { + use_lag=2*lag; + } + + /* compute concealed residual */ + + energy = 0.0; + for (i=0; iblockl; i++) { + + /* noise component */ + + iLBCdec_inst->seed=(iLBCdec_inst->seed*69069L+1) & + (0x80000000L-1); + randlag = 50 + ((signed long) iLBCdec_inst->seed)%70; + pick = i - randlag; + + if (pick < 0) { + randvec[i] = + iLBCdec_inst->prevResidual[ + iLBCdec_inst->blockl+pick]; + } else { + randvec[i] = randvec[pick]; + } + + /* pitch repeatition component */ + pick = i - use_lag; + + if (pick < 0) { + PLCresidual[i] = + iLBCdec_inst->prevResidual[ + iLBCdec_inst->blockl+pick]; + } else { + PLCresidual[i] = PLCresidual[pick]; + } + + /* mix random and periodicity component */ + + if (i<80) + PLCresidual[i] = use_gain*(pitchfact * + + + PLCresidual[i] + + ((float)1.0 - pitchfact) * randvec[i]); + else if (i<160) + PLCresidual[i] = (float)0.95*use_gain*(pitchfact * + PLCresidual[i] + + ((float)1.0 - pitchfact) * randvec[i]); + else + PLCresidual[i] = (float)0.9*use_gain*(pitchfact * + PLCresidual[i] + + ((float)1.0 - pitchfact) * randvec[i]); + + energy += PLCresidual[i] * PLCresidual[i]; + } + + /* less than 30 dB, use only noise */ + + if (sqrt(energy/(float)iLBCdec_inst->blockl) < 30.0) { + gain=0.0; + for (i=0; iblockl; i++) { + PLCresidual[i] = randvec[i]; + } + } + + /* use old LPC */ + + memcpy(PLClpc,iLBCdec_inst->prevLpc, + (LPC_FILTERORDER+1)*sizeof(float)); + + } + + /* no packet loss, copy input */ + + else { + memcpy(PLCresidual, decresidual, + iLBCdec_inst->blockl*sizeof(float)); + memcpy(PLClpc, lpc, (LPC_FILTERORDER+1)*sizeof(float)); + iLBCdec_inst->consPLICount = 0; + } + + /* update state */ + + if (PLI) { + iLBCdec_inst->prevLag = lag; + iLBCdec_inst->per=max_per; + } + + iLBCdec_inst->prevPLI = PLI; + memcpy(iLBCdec_inst->prevLpc, PLClpc, + (LPC_FILTERORDER+1)*sizeof(float)); + memcpy(iLBCdec_inst->prevResidual, PLCresidual, + iLBCdec_inst->blockl*sizeof(float)); +} + + + + diff --git a/libs/codec/ilbc/doCPLC.h b/libs/codec/ilbc/doCPLC.h new file mode 100644 index 0000000000..778367440d --- /dev/null +++ b/libs/codec/ilbc/doCPLC.h @@ -0,0 +1,32 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + doCPLC.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + + + +******************************************************************/ + +#ifndef __iLBC_DOLPC_H +#define __iLBC_DOLPC_H + +void doThePLC( + float *PLCresidual, /* (o) concealed residual */ + float *PLClpc, /* (o) concealed LP parameters */ + int PLI, /* (i) packet loss indicator + 0 - no PL, 1 = PL */ + float *decresidual, /* (i) decoded residual */ + float *lpc, /* (i) decoded LPC (only used for no PL) */ + int inlag, /* (i) pitch lag */ + iLBC_Dec_Inst_t *iLBCdec_inst + /* (i/o) decoder instance */ +); + +#endif + + diff --git a/libs/codec/ilbc/enhancer.c b/libs/codec/ilbc/enhancer.c new file mode 100644 index 0000000000..435811330e --- /dev/null +++ b/libs/codec/ilbc/enhancer.c @@ -0,0 +1,665 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + enhancer.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include +#include +#include "iLBC_define.h" +#include "enhancer.h" +#include "constants.h" +#include "filter.h" + +/*----------------------------------------------------------------* + + + * Find index in array such that the array element with said + * index is the element of said array closest to "value" + * according to the squared-error criterion + *---------------------------------------------------------------*/ + +static void NearestNeighbor( + int *index, /* (o) index of array element closest + to value */ + float *array, /* (i) data array */ + float value,/* (i) value */ + int arlength/* (i) dimension of data array */ +){ + int i; + float bestcrit,crit; + + crit=array[0]-value; + bestcrit=crit*crit; + *index=0; + for (i=1; i dim1 ) { + hfl2=(int) (dim1/2); + for (j=0; j= idatal) { + searchSegEndPos=idatal-ENH_BLOCKL-1; + } + corrdim=searchSegEndPos-searchSegStartPos+1; + + /* compute upsampled correlation (corr33) and find + location of max */ + + mycorr1(corrVec,idata+searchSegStartPos, + corrdim+ENH_BLOCKL-1,idata+centerStartPos,ENH_BLOCKL); + enh_upsample(corrVecUps,corrVec,corrdim,ENH_FL0); + tloc=0; maxv=corrVecUps[0]; + for (i=1; imaxv) { + tloc=i; + maxv=corrVecUps[i]; + } + } + + /* make vector can be upsampled without ever running outside + bounds */ + + *updStartPos= (float)searchSegStartPos + + (float)tloc/(float)ENH_UPS0+(float)1.0; + tloc2=(int)(tloc/ENH_UPS0); + + if (tloc>tloc2*ENH_UPS0) { + tloc2++; + } + st=searchSegStartPos+tloc2-ENH_FL0; + + if (st<0) { + memset(vect,0,-st*sizeof(float)); + memcpy(&vect[-st],idata, (ENH_VECTL+st)*sizeof(float)); + } + else { + en=st+ENH_VECTL; + + if (en>idatal) { + memcpy(vect, &idata[st], + (ENH_VECTL-(en-idatal))*sizeof(float)); + memset(&vect[ENH_VECTL-(en-idatal)], 0, + (en-idatal)*sizeof(float)); + } + else { + memcpy(vect, &idata[st], ENH_VECTL*sizeof(float)); + } + } + fraction=tloc2*ENH_UPS0-tloc; + + /* compute the segment (this is actually a convolution) */ + + mycorr1(seg,vect,ENH_VECTL,polyphaserTbl+(2*ENH_FL0+1)*fraction, + + + 2*ENH_FL0+1); +} + +/*----------------------------------------------------------------* + * find the smoothed output data + *---------------------------------------------------------------*/ + +static void smath( + float *odata, /* (o) smoothed output */ + float *sseq,/* (i) said second sequence of waveforms */ + int hl, /* (i) 2*hl+1 is sseq dimension */ + float alpha0/* (i) max smoothing energy fraction */ +){ + int i,k; + float w00,w10,w11,A,B,C,*psseq,err,errs; + float surround[BLOCKL_MAX]; /* shape contributed by other than + current */ + float wt[2*ENH_HL+1]; /* waveform weighting to get + surround shape */ + float denom; + + /* create shape of contribution from all waveforms except the + current one */ + + for (i=1; i<=2*hl+1; i++) { + wt[i-1] = (float)0.5*(1 - (float)cos(2*PI*i/(2*hl+2))); + } + wt[hl]=0.0; /* for clarity, not used */ + for (i=0; i alpha0 * w00) { + if ( w00 < 1) { + w00=1; + } + denom = (w11*w00-w10*w10)/(w00*w00); + + if (denom > 0.0001) { /* eliminates numerical problems + for if smooth */ + A = (float)sqrt( (alpha0- alpha0*alpha0/4)/denom); + B = -alpha0/2 - A * w10/w00; + B = B+1; + } + else { /* essentially no difference between cycles; + smoothing not needed */ + A= 0.0; + B= 1.0; + } + + /* create smoothed sequence */ + + psseq=sseq+hl*ENH_BLOCKL; + for (i=0; i=0; q--) { + blockStartPos[q]=blockStartPos[q+1]-period[lagBlock[q+1]]; + NearestNeighbor(lagBlock+q,plocs, + blockStartPos[q]+ + ENH_BLOCKL_HALF-period[lagBlock[q+1]], periodl); + + + if (blockStartPos[q]-ENH_OVERHANG>=0) { + refiner(sseq+q*ENH_BLOCKL, blockStartPos+q, idata, + idatal, centerStartPos, blockStartPos[q], + period[lagBlock[q+1]]); + } else { + psseq=sseq+q*ENH_BLOCKL; + memset(psseq, 0, ENH_BLOCKL*sizeof(float)); + } + } + + /* future */ + + for (i=0; i 0.0) { + return (float)(ftmp1*ftmp1/ftmp2); + } + else { + return (float)0.0; + } +} + +/*----------------------------------------------------------------* + * interface for enhancer + *---------------------------------------------------------------*/ + +int enhancerInterface( + float *out, /* (o) enhanced signal */ + float *in, /* (i) unenhanced signal */ + iLBC_Dec_Inst_t *iLBCdec_inst /* (i) buffers etc */ +){ + float *enh_buf, *enh_period; + int iblock, isample; + int lag=0, ilag, i, ioffset; + float cc, maxcc; + float ftmp1, ftmp2; + float *inPtr, *enh_bufPtr1, *enh_bufPtr2; + float plc_pred[ENH_BLOCKL]; + + float lpState[6], downsampled[(ENH_NBLOCKS*ENH_BLOCKL+120)/2]; + int inLen=ENH_NBLOCKS*ENH_BLOCKL+120; + int start, plc_blockl, inlag; + + enh_buf=iLBCdec_inst->enh_buf; + enh_period=iLBCdec_inst->enh_period; + + memmove(enh_buf, &enh_buf[iLBCdec_inst->blockl], + (ENH_BUFL-iLBCdec_inst->blockl)*sizeof(float)); + + memcpy(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl], in, + iLBCdec_inst->blockl*sizeof(float)); + + if (iLBCdec_inst->mode==30) + plc_blockl=ENH_BLOCKL; + else + plc_blockl=40; + + /* when 20 ms frame, move processing one block */ + ioffset=0; + if (iLBCdec_inst->mode==20) ioffset=1; + + i=3-ioffset; + memmove(enh_period, &enh_period[i], + + + (ENH_NBLOCKS_TOT-i)*sizeof(float)); + + /* Set state information to the 6 samples right before + the samples to be downsampled. */ + + memcpy(lpState, + enh_buf+(ENH_NBLOCKS_EXTRA+ioffset)*ENH_BLOCKL-126, + 6*sizeof(float)); + + /* Down sample a factor 2 to save computations */ + + DownSample(enh_buf+(ENH_NBLOCKS_EXTRA+ioffset)*ENH_BLOCKL-120, + lpFilt_coefsTbl, inLen-ioffset*ENH_BLOCKL, + lpState, downsampled); + + /* Estimate the pitch in the down sampled domain. */ + for (iblock = 0; iblock maxcc) { + maxcc = cc; + lag = ilag; + } + } + + /* Store the estimated lag in the non-downsampled domain */ + enh_period[iblock+ENH_NBLOCKS_EXTRA+ioffset] = (float)lag*2; + + + } + + + /* PLC was performed on the previous packet */ + if (iLBCdec_inst->prev_enh_pl==1) { + + inlag=(int)enh_period[ENH_NBLOCKS_EXTRA+ioffset]; + + lag = inlag-1; + maxcc = xCorrCoef(in, in+lag, plc_blockl); + for (ilag=inlag; ilag<=inlag+1; ilag++) { + cc = xCorrCoef(in, in+ilag, plc_blockl); + + if (cc > maxcc) { + maxcc = cc; + lag = ilag; + } + } + + + + enh_period[ENH_NBLOCKS_EXTRA+ioffset-1]=(float)lag; + + /* compute new concealed residual for the old lookahead, + mix the forward PLC with a backward PLC from + the new frame */ + + inPtr=&in[lag-1]; + + enh_bufPtr1=&plc_pred[plc_blockl-1]; + + if (lag>plc_blockl) { + start=plc_blockl; + } else { + start=lag; + } + + for (isample = start; isample>0; isample--) { + *enh_bufPtr1-- = *inPtr--; + } + + enh_bufPtr2=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl]; + for (isample = (plc_blockl-1-lag); isample>=0; isample--) +{ + *enh_bufPtr1-- = *enh_bufPtr2--; + } + + /* limit energy change */ + ftmp2=0.0; + ftmp1=0.0; + for (i=0;iblockl-i]* + enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl-i]; + ftmp1+=plc_pred[i]*plc_pred[i]; + } + ftmp1=(float)sqrt(ftmp1/(float)plc_blockl); + ftmp2=(float)sqrt(ftmp2/(float)plc_blockl); + if (ftmp1>(float)2.0*ftmp2 && ftmp1>0.0) { + for (i=0;iblockl]; + for (i=0; imode==20) { + /* Enhancer with 40 samples delay */ + for (iblock = 0; iblock<2; iblock++) { + enhancer(out+iblock*ENH_BLOCKL, enh_buf, + ENH_BUFL, (5+iblock)*ENH_BLOCKL+40, + ENH_ALPHA0, enh_period, enh_plocsTbl, + ENH_NBLOCKS_TOT); + } + } else if (iLBCdec_inst->mode==30) { + /* Enhancer with 80 samples delay */ + for (iblock = 0; iblock<3; iblock++) { + enhancer(out+iblock*ENH_BLOCKL, enh_buf, + ENH_BUFL, (4+iblock)*ENH_BLOCKL, + ENH_ALPHA0, enh_period, enh_plocsTbl, + ENH_NBLOCKS_TOT); + } + } + + return (lag*2); +} + + diff --git a/libs/codec/ilbc/enhancer.h b/libs/codec/ilbc/enhancer.h new file mode 100644 index 0000000000..dab29ec53d --- /dev/null +++ b/libs/codec/ilbc/enhancer.h @@ -0,0 +1,33 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + enhancer.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#ifndef __ENHANCER_H +#define __ENHANCER_H + +#include "iLBC_define.h" + +float xCorrCoef( + float *target, /* (i) first array */ + float *regressor, /* (i) second array */ + int subl /* (i) dimension arrays */ +); + +int enhancerInterface( + float *out, /* (o) the enhanced recidual signal */ + float *in, /* (i) the recidual signal to enhance */ + iLBC_Dec_Inst_t *iLBCdec_inst + /* (i/o) the decoder state structure */ +); + +#endif + + diff --git a/libs/codec/ilbc/filter.c b/libs/codec/ilbc/filter.c new file mode 100644 index 0000000000..1215e313ac --- /dev/null +++ b/libs/codec/ilbc/filter.c @@ -0,0 +1,168 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + filter.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + + + +#include "iLBC_define.h" +#include "filter.h" + +/*----------------------------------------------------------------* + * all-pole filter + *---------------------------------------------------------------*/ + +void AllPoleFilter( + float *InOut, /* (i/o) on entrance InOut[-orderCoef] to + InOut[-1] contain the state of the + filter (delayed samples). InOut[0] to + InOut[lengthInOut-1] contain the filter + input, on en exit InOut[-orderCoef] to + InOut[-1] is unchanged and InOut[0] to + InOut[lengthInOut-1] contain filtered + samples */ + float *Coef,/* (i) filter coefficients, Coef[0] is assumed + to be 1.0 */ + int lengthInOut,/* (i) number of input/output samples */ + int orderCoef /* (i) number of filter coefficients */ +){ + int n,k; + + for(n=0;n +#include +#include "constants.h" +#include "gainquant.h" +#include "filter.h" + +/*----------------------------------------------------------------* + * quantizer for the gain in the gain-shape coding of residual + *---------------------------------------------------------------*/ + +float gainquant(/* (o) quantized gain value */ + float in, /* (i) gain value */ + float maxIn,/* (i) maximum of gain value */ + int cblen, /* (i) number of quantization indices */ + int *index /* (o) quantization index */ +){ + int i, tindex; + float minmeasure,measure, *cb, scale; + + /* ensure a lower bound on the scaling factor */ + + scale=maxIn; + + if (scale<0.1) { + scale=(float)0.1; + } + + /* select the quantization table */ + + if (cblen == 8) { + cb = gain_sq3Tbl; + } else if (cblen == 16) { + cb = gain_sq4Tbl; + } else { + cb = gain_sq5Tbl; + } + + /* select the best index in the quantization table */ + + minmeasure=10000000.0; + tindex=0; + for (i=0; i + +/*----------------------------------------------------------------* + * Construct codebook vector for given index. + *---------------------------------------------------------------*/ + +void getCBvec( + float *cbvec, /* (o) Constructed codebook vector */ + float *mem, /* (i) Codebook buffer */ + int index, /* (i) Codebook index */ + int lMem, /* (i) Length of codebook buffer */ + int cbveclen/* (i) Codebook vector length */ +){ + int j, k, n, memInd, sFilt; + float tmpbuf[CB_MEML]; + int base_size; + int ilow, ihigh; + float alfa, alfa1; + + /* Determine size of codebook sections */ + + base_size=lMem-cbveclen+1; + + if (cbveclen==SUBL) { + base_size+=cbveclen/2; + } + + /* No filter -> First codebook section */ + + + + if (index + +#include "iLBC_define.h" +#include "helpfun.h" +#include "constants.h" + +/*----------------------------------------------------------------* + * calculation of auto correlation + *---------------------------------------------------------------*/ + +void autocorr( + float *r, /* (o) autocorrelation vector */ + const float *x, /* (i) data vector */ + int N, /* (i) length of data vector */ + int order /* largest lag for calculated + autocorrelations */ +){ + int lag, n; + float sum; + + for (lag = 0; lag <= order; lag++) { + sum = 0; + for (n = 0; n < N - lag; n++) { + sum += x[n] * x[n+lag]; + } + r[lag] = sum; + } +} + + + +/*----------------------------------------------------------------* + * window multiplication + *---------------------------------------------------------------*/ + +void window( + float *z, /* (o) the windowed data */ + const float *x, /* (i) the original data vector */ + const float *y, /* (i) the window */ + int N /* (i) length of all vectors */ +){ + int i; + + for (i = 0; i < N; i++) { + z[i] = x[i] * y[i]; + } +} + +/*----------------------------------------------------------------* + * levinson-durbin solution for lpc coefficients + *---------------------------------------------------------------*/ + +void levdurb( + float *a, /* (o) lpc coefficient vector starting + with 1.0 */ + float *k, /* (o) reflection coefficients */ + float *r, /* (i) autocorrelation vector */ + int order /* (i) order of lpc filter */ +){ + float sum, alpha; + int m, m_h, i; + + a[0] = 1.0; + + if (r[0] < EPS) { /* if r[0] <= 0, set LPC coeff. to zero */ + for (i = 0; i < order; i++) { + k[i] = 0; + a[i+1] = 0; + } + } else { + a[1] = k[0] = -r[1]/r[0]; + alpha = r[0] + r[1] * k[0]; + for (m = 1; m < order; m++){ + sum = r[m + 1]; + for (i = 0; i < m; i++){ + sum += a[i+1] * r[m - i]; + } + k[m] = -sum / alpha; + alpha += k[m] * sum; + m_h = (m + 1) >> 1; + for (i = 0; i < m_h; i++){ + sum = a[i+1] + k[m] * a[m - i]; + a[m - i] += k[m] * a[i+1]; + a[i+1] = sum; + + + } + a[m+1] = k[m]; + } + } +} + +/*----------------------------------------------------------------* + * interpolation between vectors + *---------------------------------------------------------------*/ + +void interpolate( + float *out, /* (o) the interpolated vector */ + float *in1, /* (i) the first vector for the + interpolation */ + float *in2, /* (i) the second vector for the + interpolation */ + float coef, /* (i) interpolation weights */ + int length /* (i) length of all vectors */ +){ + int i; + float invcoef; + + invcoef = (float)1.0 - coef; + for (i = 0; i < length; i++) { + out[i] = coef * in1[i] + invcoef * in2[i]; + } +} + +/*----------------------------------------------------------------* + * lpc bandwidth expansion + *---------------------------------------------------------------*/ + +void bwexpand( + float *out, /* (o) the bandwidth expanded lpc + coefficients */ + float *in, /* (i) the lpc coefficients before bandwidth + expansion */ + float coef, /* (i) the bandwidth expansion factor */ + int length /* (i) the length of lpc coefficient vectors */ +){ + int i; + float chirp; + + chirp = coef; + + out[0] = in[0]; + for (i = 1; i < length; i++) { + out[i] = chirp * in[i]; + chirp *= coef; + } +} + +/*----------------------------------------------------------------* + * vector quantization + + + *---------------------------------------------------------------*/ + +void vq( + float *Xq, /* (o) the quantized vector */ + int *index, /* (o) the quantization index */ + const float *CB,/* (i) the vector quantization codebook */ + float *X, /* (i) the vector to quantize */ + int n_cb, /* (i) the number of vectors in the codebook */ + int dim /* (i) the dimension of all vectors */ +){ + int i, j; + int pos, minindex; + float dist, tmp, mindist; + + pos = 0; + mindist = FLOAT_MAX; + minindex = 0; + for (j = 0; j < n_cb; j++) { + dist = X[0] - CB[pos]; + dist *= dist; + for (i = 1; i < dim; i++) { + tmp = X[i] - CB[pos + i]; + dist += tmp*tmp; + } + + if (dist < mindist) { + mindist = dist; + minindex = j; + } + pos += dim; + } + for (i = 0; i < dim; i++) { + Xq[i] = CB[minindex*dim + i]; + } + *index = minindex; +} + +/*----------------------------------------------------------------* + * split vector quantization + *---------------------------------------------------------------*/ + +void SplitVQ( + float *qX, /* (o) the quantized vector */ + int *index, /* (o) a vector of indexes for all vector + codebooks in the split */ + float *X, /* (i) the vector to quantize */ + const float *CB,/* (i) the quantizer codebook */ + int nsplit, /* the number of vector splits */ + const int *dim, /* the dimension of X and qX */ + const int *cbsize /* the number of vectors in the codebook */ +){ + int cb_pos, X_pos, i; + + cb_pos = 0; + + + X_pos= 0; + for (i = 0; i < nsplit; i++) { + vq(qX + X_pos, index + i, CB + cb_pos, X + X_pos, + cbsize[i], dim[i]); + X_pos += dim[i]; + cb_pos += dim[i] * cbsize[i]; + } +} + +/*----------------------------------------------------------------* + * scalar quantization + *---------------------------------------------------------------*/ + +void sort_sq( + float *xq, /* (o) the quantized value */ + int *index, /* (o) the quantization index */ + float x, /* (i) the value to quantize */ + const float *cb,/* (i) the quantization codebook */ + int cb_size /* (i) the size of the quantization codebook */ +){ + int i; + + if (x <= cb[0]) { + *index = 0; + *xq = cb[0]; + } else { + i = 0; + while ((x > cb[i]) && i < cb_size - 1) { + i++; + } + + if (x > ((cb[i] + cb[i - 1])/2)) { + *index = i; + *xq = cb[i]; + } else { + *index = i - 1; + *xq = cb[i - 1]; + } + } +} + +/*----------------------------------------------------------------* + * check for stability of lsf coefficients + *---------------------------------------------------------------*/ + +int LSF_check( /* (o) 1 for stable lsf vectors and 0 for + nonstable ones */ + float *lsf, /* (i) a table of lsf vectors */ + int dim, /* (i) the dimension of each lsf vector */ + int NoAn /* (i) the number of lsf vectors in the + table */ +){ + int k,n,m, Nit=2, change=0,pos; + float tmp; + + + static float eps=(float)0.039; /* 50 Hz */ + static float eps2=(float)0.0195; + static float maxlsf=(float)3.14; /* 4000 Hz */ + static float minlsf=(float)0.01; /* 0 Hz */ + + /* LSF separation check*/ + + for (n=0; nmaxlsf) { + lsf[pos]=maxlsf; + change=1; + } + } + } + } + + return change; +} + + diff --git a/libs/codec/ilbc/helpfun.h b/libs/codec/ilbc/helpfun.h new file mode 100644 index 0000000000..e2bc4b1340 --- /dev/null +++ b/libs/codec/ilbc/helpfun.h @@ -0,0 +1,101 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + helpfun.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#ifndef __iLBC_HELPFUN_H +#define __iLBC_HELPFUN_H + +void autocorr( + float *r, /* (o) autocorrelation vector */ + const float *x, /* (i) data vector */ + int N, /* (i) length of data vector */ + int order /* largest lag for calculated + autocorrelations */ +); + +void window( + float *z, /* (o) the windowed data */ + const float *x, /* (i) the original data vector */ + const float *y, /* (i) the window */ + int N /* (i) length of all vectors */ +); + + + +void levdurb( + float *a, /* (o) lpc coefficient vector starting + with 1.0 */ + float *k, /* (o) reflection coefficients */ + float *r, /* (i) autocorrelation vector */ + int order /* (i) order of lpc filter */ +); + +void interpolate( + float *out, /* (o) the interpolated vector */ + float *in1, /* (i) the first vector for the + interpolation */ + float *in2, /* (i) the second vector for the + interpolation */ + float coef, /* (i) interpolation weights */ + int length /* (i) length of all vectors */ +); + +void bwexpand( + float *out, /* (o) the bandwidth expanded lpc + coefficients */ + float *in, /* (i) the lpc coefficients before bandwidth + expansion */ + float coef, /* (i) the bandwidth expansion factor */ + int length /* (i) the length of lpc coefficient vectors */ +); + +void vq( + float *Xq, /* (o) the quantized vector */ + int *index, /* (o) the quantization index */ + const float *CB,/* (i) the vector quantization codebook */ + float *X, /* (i) the vector to quantize */ + int n_cb, /* (i) the number of vectors in the codebook */ + int dim /* (i) the dimension of all vectors */ +); + +void SplitVQ( + float *qX, /* (o) the quantized vector */ + int *index, /* (o) a vector of indexes for all vector + codebooks in the split */ + float *X, /* (i) the vector to quantize */ + const float *CB,/* (i) the quantizer codebook */ + int nsplit, /* the number of vector splits */ + const int *dim, /* the dimension of X and qX */ + const int *cbsize /* the number of vectors in the codebook */ +); + + +void sort_sq( + float *xq, /* (o) the quantized value */ + int *index, /* (o) the quantization index */ + float x, /* (i) the value to quantize */ + const float *cb,/* (i) the quantization codebook */ + + + int cb_size /* (i) the size of the quantization codebook */ +); + +int LSF_check( /* (o) 1 for stable lsf vectors and 0 for + nonstable ones */ + float *lsf, /* (i) a table of lsf vectors */ + int dim, /* (i) the dimension of each lsf vector */ + int NoAn /* (i) the number of lsf vectors in the + table */ +); + +#endif + + diff --git a/libs/codec/ilbc/hpInput.c b/libs/codec/ilbc/hpInput.c new file mode 100644 index 0000000000..54d997e755 --- /dev/null +++ b/libs/codec/ilbc/hpInput.c @@ -0,0 +1,60 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + hpInput.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include "constants.h" +#include "hpInput.h" + +/*----------------------------------------------------------------* + * Input high-pass filter + *---------------------------------------------------------------*/ + +void hpInput( + float *In, /* (i) vector to filter */ + int len, /* (i) length of vector to filter */ + float *Out, /* (o) the resulting filtered vector */ + float *mem /* (i/o) the filter state */ +){ + int i; + float *pi, *po; + + /* all-zero section*/ + + pi = &In[0]; + po = &Out[0]; + for (i=0; i + +#include "iLBC_define.h" +#include "iCBConstruct.h" +#include "gainquant.h" +#include "getCBvec.h" + +/*----------------------------------------------------------------* + * Convert the codebook indexes to make the search easier + *---------------------------------------------------------------*/ + + + +void index_conv_enc( + int *index /* (i/o) Codebook indexes */ +){ + int k; + + for (k=1; k=108)&&(index[k]<172)) { + index[k]-=64; + } else if (index[k]>=236) { + index[k]-=128; + } else { + /* ERROR */ + } + } +} + +void index_conv_dec( + int *index /* (i/o) Codebook indexes */ +){ + int k; + + for (k=1; k=44)&&(index[k]<108)) { + index[k]+=64; + } else if ((index[k]>=108)&&(index[k]<128)) { + index[k]+=128; + } else { + /* ERROR */ + } + } +} + +/*----------------------------------------------------------------* + * Construct decoded vector from codebook and gains. + *---------------------------------------------------------------*/ + +void iCBConstruct( + float *decvector, /* (o) Decoded vector */ + int *index, /* (i) Codebook indices */ + int *gain_index,/* (i) Gain quantization indices */ + float *mem, /* (i) Buffer for codevector construction */ + int lMem, /* (i) Length of buffer */ + int veclen, /* (i) Length of vector */ + int nStages /* (i) Number of codebook stages */ +){ + int j,k; + float gain[CB_NSTAGES]; + float cbvec[SUBL]; + + /* gain de-quantization */ + + gain[0] = gaindequant(gain_index[0], 1.0, 32); + + + if (nStages > 1) { + gain[1] = gaindequant(gain_index[1], + (float)fabs(gain[0]), 16); + } + if (nStages > 2) { + gain[2] = gaindequant(gain_index[2], + (float)fabs(gain[1]), 8); + } + + /* codebook vector construction and construction of + total vector */ + + getCBvec(cbvec, mem, index[0], lMem, veclen); + for (j=0;j 1) { + for (k=1; k +#include + +#include "iLBC_define.h" +#include "iCBSearch.h" +#include "gainquant.h" +#include "createCB.h" +#include "filter.h" +#include "constants.h" + +/*----------------------------------------------------------------* + * Search routine for codebook encoding and gain quantization. + *---------------------------------------------------------------*/ + +void iCBSearch( + iLBC_Enc_Inst_t *iLBCenc_inst, + /* (i) the encoder state structure */ + int *index, /* (o) Codebook indices */ + int *gain_index,/* (o) Gain quantization indices */ + float *intarget,/* (i) Target vector for encoding */ + float *mem, /* (i) Buffer for codebook construction */ + int lMem, /* (i) Length of buffer */ + int lTarget, /* (i) Length of vector */ + int nStages, /* (i) Number of codebook stages */ + float *weightDenum, /* (i) weighting filter coefficients */ + float *weightState, /* (i) weighting filter state */ + int block /* (i) the sub-block number */ +){ + int i, j, icount, stage, best_index, range, counter; + float max_measure, gain, measure, crossDot, ftmp; + float gains[CB_NSTAGES]; + float target[SUBL]; + int base_index, sInd, eInd, base_size; + int sIndAug=0, eIndAug=0; + float buf[CB_MEML+SUBL+2*LPC_FILTERORDER]; + + + float invenergy[CB_EXPAND*128], energy[CB_EXPAND*128]; + float *pp, *ppi=0, *ppo=0, *ppe=0; + float cbvectors[CB_MEML]; + float tene, cene, cvec[SUBL]; + float aug_vec[SUBL]; + + memset(cvec,0,SUBL*sizeof(float)); + + /* Determine size of codebook sections */ + + base_size=lMem-lTarget+1; + + if (lTarget==SUBL) { + base_size=lMem-lTarget+1+lTarget/2; + } + + /* setup buffer for weighting */ + + memcpy(buf,weightState,sizeof(float)*LPC_FILTERORDER); + memcpy(buf+LPC_FILTERORDER,mem,lMem*sizeof(float)); + memcpy(buf+LPC_FILTERORDER+lMem,intarget,lTarget*sizeof(float)); + + /* weighting */ + + AllPoleFilter(buf+LPC_FILTERORDER, weightDenum, + lMem+lTarget, LPC_FILTERORDER); + + /* Construct the codebook and target needed */ + + memcpy(target, buf+LPC_FILTERORDER+lMem, lTarget*sizeof(float)); + + tene=0.0; + for (i=0; i0.0) { + invenergy[0] = (float) 1.0 / (*ppe + EPS); + } else { + invenergy[0] = (float) 0.0; + } + ppe++; + + measure=(float)-10000000.0; + + if (crossDot > 0.0) { + measure = crossDot*crossDot*invenergy[0]; + } + } + else { + measure = crossDot*crossDot*invenergy[0]; + } + + /* check if measure is better */ + ftmp = crossDot*invenergy[0]; + + if ((measure>max_measure) && (fabs(ftmp)0.0) { + invenergy[icount] = + (float)1.0/(energy[icount]+EPS); + } else { + invenergy[icount] = (float) 0.0; + } + + measure=(float)-10000000.0; + + if (crossDot > 0.0) { + measure = crossDot*crossDot*invenergy[icount]; + } + } + else { + measure = crossDot*crossDot*invenergy[icount]; + } + + /* check if measure is better */ + ftmp = crossDot*invenergy[icount]; + + if ((measure>max_measure) && (fabs(ftmp) range) { + sInd -= (eInd-range); + eInd = range; + } + } else { /* base_index >= (base_size-20) */ + + if (sInd < (base_size-20)) { + sIndAug = 20; + sInd = 0; + eInd = 0; + eIndAug = 19 + CB_RESRANGE; + + if(eIndAug > 39) { + eInd = eIndAug-39; + eIndAug = 39; + } + } else { + sIndAug = 20 + sInd - (base_size-20); + eIndAug = 39; + + + sInd = 0; + eInd = CB_RESRANGE - (eIndAug-sIndAug+1); + } + } + + } else { /* lTarget = 22 or 23 */ + + if (sInd < 0) { + eInd -= sInd; + sInd = 0; + } + + if(eInd > range) { + sInd -= (eInd - range); + eInd = range; + } + } + } + + /* search of higher codebook section */ + + /* index search range */ + counter = sInd; + sInd += base_size; + eInd += base_size; + + + if (stage==0) { + ppe = energy+base_size; + *ppe=0.0; + + pp=cbvectors+lMem-lTarget; + for (j=0; j0.0) { + invenergy[icount] =(float)1.0/(energy[icount]+EPS); + } else { + invenergy[icount] =(float)0.0; + } + + if (stage==0) { + + measure=(float)-10000000.0; + + if (crossDot > 0.0) { + measure = crossDot*crossDot* + invenergy[icount]; + } + } + else { + measure = crossDot*crossDot*invenergy[icount]; + } + + /* check if measure is better */ + ftmp = crossDot*invenergy[icount]; + + if ((measure>max_measure) && (fabs(ftmp)CB_MAXGAIN) { + gain = (float)CB_MAXGAIN; + } + gain = gainquant(gain, 1.0, 32, &gain_index[stage]); + } + else { + if (stage==1) { + gain = gainquant(gain, (float)fabs(gains[stage-1]), + 16, &gain_index[stage]); + } else { + gain = gainquant(gain, (float)fabs(gains[stage-1]), + 8, &gain_index[stage]); + } + } + + /* Extract the best (according to measure) + codebook vector */ + + if (lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) { + + if (index[stage] +#include + +#include "iLBC_define.h" +#include "iLBC_decode.h" +#include "StateConstructW.h" +#include "LPCdecode.h" +#include "iCBConstruct.h" +#include "doCPLC.h" +#include "helpfun.h" +#include "constants.h" +#include "packing.h" +#include "string.h" +#include "enhancer.h" +#include "hpOutput.h" +#include "syntFilter.h" + +/*----------------------------------------------------------------* + * Initiation of decoder instance. + *---------------------------------------------------------------*/ + +short initDecode( /* (o) Number of decoded + samples */ + iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) Decoder instance */ + int mode, /* (i) frame size mode */ + int use_enhancer /* (i) 1 to use enhancer + 0 to run without + enhancer */ +){ + int i; + + iLBCdec_inst->mode = mode; + + if (mode==30) { + iLBCdec_inst->blockl = BLOCKL_30MS; + iLBCdec_inst->nsub = NSUB_30MS; + iLBCdec_inst->nasub = NASUB_30MS; + iLBCdec_inst->lpc_n = LPC_N_30MS; + + + iLBCdec_inst->no_of_bytes = NO_OF_BYTES_30MS; + iLBCdec_inst->no_of_words = NO_OF_WORDS_30MS; + iLBCdec_inst->state_short_len=STATE_SHORT_LEN_30MS; + /* ULP init */ + iLBCdec_inst->ULP_inst=&ULP_30msTbl; + } + else if (mode==20) { + iLBCdec_inst->blockl = BLOCKL_20MS; + iLBCdec_inst->nsub = NSUB_20MS; + iLBCdec_inst->nasub = NASUB_20MS; + iLBCdec_inst->lpc_n = LPC_N_20MS; + iLBCdec_inst->no_of_bytes = NO_OF_BYTES_20MS; + iLBCdec_inst->no_of_words = NO_OF_WORDS_20MS; + iLBCdec_inst->state_short_len=STATE_SHORT_LEN_20MS; + /* ULP init */ + iLBCdec_inst->ULP_inst=&ULP_20msTbl; + } + else { + exit(2); + } + + memset(iLBCdec_inst->syntMem, 0, + LPC_FILTERORDER*sizeof(float)); + memcpy((*iLBCdec_inst).lsfdeqold, lsfmeanTbl, + LPC_FILTERORDER*sizeof(float)); + + memset(iLBCdec_inst->old_syntdenum, 0, + ((LPC_FILTERORDER + 1)*NSUB_MAX)*sizeof(float)); + for (i=0; iold_syntdenum[i*(LPC_FILTERORDER+1)]=1.0; + + iLBCdec_inst->last_lag = 20; + + iLBCdec_inst->prevLag = 120; + iLBCdec_inst->per = 0.0; + iLBCdec_inst->consPLICount = 0; + iLBCdec_inst->prevPLI = 0; + iLBCdec_inst->prevLpc[0] = 1.0; + memset(iLBCdec_inst->prevLpc+1,0, + LPC_FILTERORDER*sizeof(float)); + memset(iLBCdec_inst->prevResidual, 0, BLOCKL_MAX*sizeof(float)); + iLBCdec_inst->seed=777; + + memset(iLBCdec_inst->hpomem, 0, 4*sizeof(float)); + + iLBCdec_inst->use_enhancer = use_enhancer; + memset(iLBCdec_inst->enh_buf, 0, ENH_BUFL*sizeof(float)); + for (i=0;ienh_period[i]=(float)40.0; + + iLBCdec_inst->prev_enh_pl = 0; + + return (iLBCdec_inst->blockl); +} + + + +/*----------------------------------------------------------------* + * frame residual decoder function (subrutine to iLBC_decode) + *---------------------------------------------------------------*/ + +static void Decode( + iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state + structure */ + float *decresidual, /* (o) decoded residual frame */ + int start, /* (i) location of start + state */ + int idxForMax, /* (i) codebook index for the + maximum value */ + int *idxVec, /* (i) codebook indexes for the + samples in the start + state */ + float *syntdenum, /* (i) the decoded synthesis + filter coefficients */ + int *cb_index, /* (i) the indexes for the + adaptive codebook */ + int *gain_index, /* (i) the indexes for the + corresponding gains */ + int *extra_cb_index, /* (i) the indexes for the + adaptive codebook part + of start state */ + int *extra_gain_index, /* (i) the indexes for the + corresponding gains */ + int state_first /* (i) 1 if non adaptive part + of start state comes + first 0 if that part + comes last */ +){ + float reverseDecresidual[BLOCKL_MAX], mem[CB_MEML]; + int k, meml_gotten, Nfor, Nback, i; + int diff, start_pos; + int subcount, subframe; + + diff = STATE_LEN - iLBCdec_inst->state_short_len; + + if (state_first == 1) { + start_pos = (start-1)*SUBL; + } else { + start_pos = (start-1)*SUBL + diff; + } + + /* decode scalar part of start state */ + + StateConstructW(idxForMax, idxVec, + &syntdenum[(start-1)*(LPC_FILTERORDER+1)], + &decresidual[start_pos], iLBCdec_inst->state_short_len); + + + if (state_first) { /* put adaptive part in the end */ + + + + /* setup memory */ + + memset(mem, 0, + (CB_MEML-iLBCdec_inst->state_short_len)*sizeof(float)); + memcpy(mem+CB_MEML-iLBCdec_inst->state_short_len, + decresidual+start_pos, + iLBCdec_inst->state_short_len*sizeof(float)); + + /* construct decoded vector */ + + iCBConstruct( + &decresidual[start_pos+iLBCdec_inst->state_short_len], + extra_cb_index, extra_gain_index, mem+CB_MEML-stMemLTbl, + stMemLTbl, diff, CB_NSTAGES); + + } + else {/* put adaptive part in the beginning */ + + /* create reversed vectors for prediction */ + + for (k=0; kstate_short_len)]; + } + + /* setup memory */ + + meml_gotten = iLBCdec_inst->state_short_len; + for (k=0; knsub-start-1; + + + + if ( Nfor > 0 ){ + + /* setup memory */ + + memset(mem, 0, (CB_MEML-STATE_LEN)*sizeof(float)); + memcpy(mem+CB_MEML-STATE_LEN, decresidual+(start-1)*SUBL, + STATE_LEN*sizeof(float)); + + /* loop over sub-frames to encode */ + + for (subframe=0; subframe 0 ) { + + /* setup memory */ + + meml_gotten = SUBL*(iLBCdec_inst->nsub+1-start); + + if ( meml_gotten > CB_MEML ) { + meml_gotten=CB_MEML; + } + for (k=0; k0) { /* the data are good */ + + /* decode data */ + + pbytes=bytes; + pos=0; + + /* Set everything to zero before decoding */ + + for (k=0; kstate_short_len; k++) { + idxVec[k]=0; + } + for (k=0; knasub; i++) { + for (k=0; knasub; i++) { + for (k=0; klpc_n; k++){ + unpack( &pbytes, &lastpart, + iLBCdec_inst->ULP_inst->lsf_bits[k][ulp], &pos); + packcombine(&lsf_i[k], lastpart, + iLBCdec_inst->ULP_inst->lsf_bits[k][ulp]); + } + + + + /* Start block info */ + + unpack( &pbytes, &lastpart, + iLBCdec_inst->ULP_inst->start_bits[ulp], &pos); + packcombine(&start, lastpart, + iLBCdec_inst->ULP_inst->start_bits[ulp]); + + unpack( &pbytes, &lastpart, + iLBCdec_inst->ULP_inst->startfirst_bits[ulp], &pos); + packcombine(&state_first, lastpart, + iLBCdec_inst->ULP_inst->startfirst_bits[ulp]); + + unpack( &pbytes, &lastpart, + iLBCdec_inst->ULP_inst->scale_bits[ulp], &pos); + packcombine(&idxForMax, lastpart, + iLBCdec_inst->ULP_inst->scale_bits[ulp]); + + for (k=0; kstate_short_len; k++) { + unpack( &pbytes, &lastpart, + iLBCdec_inst->ULP_inst->state_bits[ulp], &pos); + packcombine(idxVec+k, lastpart, + iLBCdec_inst->ULP_inst->state_bits[ulp]); + } + + /* 23/22 (20ms/30ms) sample block */ + + for (k=0; kULP_inst->extra_cb_index[k][ulp], + &pos); + packcombine(extra_cb_index+k, lastpart, + iLBCdec_inst->ULP_inst->extra_cb_index[k][ulp]); + } + for (k=0; kULP_inst->extra_cb_gain[k][ulp], + &pos); + packcombine(extra_gain_index+k, lastpart, + iLBCdec_inst->ULP_inst->extra_cb_gain[k][ulp]); + } + + /* The two/four (20ms/30ms) 40 sample sub-blocks */ + + for (i=0; inasub; i++) { + for (k=0; kULP_inst->cb_index[i][k][ulp], + &pos); + packcombine(cb_index+i*CB_NSTAGES+k, lastpart, + iLBCdec_inst->ULP_inst->cb_index[i][k][ulp]); + } + } + + for (i=0; inasub; i++) { + + + for (k=0; kULP_inst->cb_gain[i][k][ulp], + &pos); + packcombine(gain_index+i*CB_NSTAGES+k, lastpart, + iLBCdec_inst->ULP_inst->cb_gain[i][k][ulp]); + } + } + } + /* Extract last bit. If it is 1 this indicates an + empty/lost frame */ + unpack( &pbytes, &last_bit, 1, &pos); + + /* Check for bit errors or empty/lost frames */ + if (start<1) + mode = 0; + if (iLBCdec_inst->mode==20 && start>3) + mode = 0; + if (iLBCdec_inst->mode==30 && start>5) + mode = 0; + if (last_bit==1) + mode = 0; + + if (mode==1) { /* No bit errors was detected, + continue decoding */ + + /* adjust index */ + index_conv_dec(cb_index); + + /* decode the lsf */ + + SimplelsfDEQ(lsfdeq, lsf_i, iLBCdec_inst->lpc_n); + check=LSF_check(lsfdeq, LPC_FILTERORDER, + iLBCdec_inst->lpc_n); + DecoderInterpolateLSF(syntdenum, weightdenum, + lsfdeq, LPC_FILTERORDER, iLBCdec_inst); + + Decode(iLBCdec_inst, decresidual, start, idxForMax, + idxVec, syntdenum, cb_index, gain_index, + extra_cb_index, extra_gain_index, + state_first); + + /* preparing the plc for a future loss! */ + + doThePLC(PLCresidual, PLClpc, 0, decresidual, + syntdenum + + (LPC_FILTERORDER + 1)*(iLBCdec_inst->nsub - 1), + (*iLBCdec_inst).last_lag, iLBCdec_inst); + + + memcpy(decresidual, PLCresidual, + iLBCdec_inst->blockl*sizeof(float)); + } + + + + } + + if (mode == 0) { + /* the data is bad (either a PLC call + * was made or a severe bit error was detected) + */ + + /* packet loss conceal */ + + memset(zeros, 0, BLOCKL_MAX*sizeof(float)); + + one[0] = 1; + memset(one+1, 0, LPC_FILTERORDER*sizeof(float)); + + start=0; + + doThePLC(PLCresidual, PLClpc, 1, zeros, one, + (*iLBCdec_inst).last_lag, iLBCdec_inst); + memcpy(decresidual, PLCresidual, + iLBCdec_inst->blockl*sizeof(float)); + + order_plus_one = LPC_FILTERORDER + 1; + for (i = 0; i < iLBCdec_inst->nsub; i++) { + memcpy(syntdenum+(i*order_plus_one), PLClpc, + order_plus_one*sizeof(float)); + } + } + + if (iLBCdec_inst->use_enhancer == 1) { + + /* post filtering */ + + iLBCdec_inst->last_lag = + enhancerInterface(data, decresidual, iLBCdec_inst); + + /* synthesis filtering */ + + if (iLBCdec_inst->mode==20) { + /* Enhancer has 40 samples delay */ + i=0; + syntFilter(data + i*SUBL, + iLBCdec_inst->old_syntdenum + + (i+iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1), + SUBL, iLBCdec_inst->syntMem); + for (i=1; i < iLBCdec_inst->nsub; i++) { + syntFilter(data + i*SUBL, + syntdenum + (i-1)*(LPC_FILTERORDER+1), + SUBL, iLBCdec_inst->syntMem); + } + } else if (iLBCdec_inst->mode==30) { + /* Enhancer has 80 samples delay */ + for (i=0; i < 2; i++) { + syntFilter(data + i*SUBL, + + + iLBCdec_inst->old_syntdenum + + (i+iLBCdec_inst->nsub-2)*(LPC_FILTERORDER+1), + SUBL, iLBCdec_inst->syntMem); + } + for (i=2; i < iLBCdec_inst->nsub; i++) { + syntFilter(data + i*SUBL, + syntdenum + (i-2)*(LPC_FILTERORDER+1), SUBL, + iLBCdec_inst->syntMem); + } + } + + } else { + + /* Find last lag */ + lag = 20; + maxcc = xCorrCoef(&decresidual[BLOCKL_MAX-ENH_BLOCKL], + &decresidual[BLOCKL_MAX-ENH_BLOCKL-lag], ENH_BLOCKL); + + for (ilag=21; ilag<120; ilag++) { + cc = xCorrCoef(&decresidual[BLOCKL_MAX-ENH_BLOCKL], + &decresidual[BLOCKL_MAX-ENH_BLOCKL-ilag], + ENH_BLOCKL); + + if (cc > maxcc) { + maxcc = cc; + lag = ilag; + } + } + iLBCdec_inst->last_lag = lag; + + /* copy data and run synthesis filter */ + + memcpy(data, decresidual, + iLBCdec_inst->blockl*sizeof(float)); + for (i=0; i < iLBCdec_inst->nsub; i++) { + syntFilter(data + i*SUBL, + syntdenum + i*(LPC_FILTERORDER+1), SUBL, + iLBCdec_inst->syntMem); + } + } + + /* high pass filtering on output if desired, otherwise + copy to out */ + + hpOutput(data, iLBCdec_inst->blockl, + decblock,iLBCdec_inst->hpomem); + + /* memcpy(decblock,data,iLBCdec_inst->blockl*sizeof(float));*/ + + memcpy(iLBCdec_inst->old_syntdenum, syntdenum, + + iLBCdec_inst->nsub*(LPC_FILTERORDER+1)*sizeof(float)); + + iLBCdec_inst->prev_enh_pl=0; + + + + if (mode==0) { /* PLC was used */ + iLBCdec_inst->prev_enh_pl=1; + } +} + + diff --git a/libs/codec/ilbc/iLBC_decode.h b/libs/codec/ilbc/iLBC_decode.h new file mode 100644 index 0000000000..ae9c481041 --- /dev/null +++ b/libs/codec/ilbc/iLBC_decode.h @@ -0,0 +1,40 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + iLBC_decode.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#ifndef __iLBC_ILBCDECODE_H +#define __iLBC_ILBCDECODE_H + +#include "iLBC_define.h" + +short initDecode( /* (o) Number of decoded + samples */ + iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) Decoder instance */ + int mode, /* (i) frame size mode */ + int use_enhancer /* (i) 1 to use enhancer + 0 to run without + enhancer */ +); + +void iLBC_decode( + float *decblock, /* (o) decoded signal block */ + unsigned char *bytes, /* (i) encoded signal bits */ + iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state + structure */ + int mode /* (i) 0: bad packet, PLC, + 1: normal */ +); + + + +#endif + + diff --git a/libs/codec/ilbc/iLBC_define.h b/libs/codec/ilbc/iLBC_define.h new file mode 100644 index 0000000000..85ef7e6854 --- /dev/null +++ b/libs/codec/ilbc/iLBC_define.h @@ -0,0 +1,201 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + iLBC_define.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ +#include + +#ifndef __iLBC_ILBCDEFINE_H +#define __iLBC_ILBCDEFINE_H + +/* general codec settings */ + +#define FS (float)8000.0 +#define BLOCKL_20MS 160 +#define BLOCKL_30MS 240 +#define BLOCKL_MAX 240 +#define NSUB_20MS 4 +#define NSUB_30MS 6 +#define NSUB_MAX 6 +#define NASUB_20MS 2 +#define NASUB_30MS 4 +#define NASUB_MAX 4 +#define SUBL 40 +#define STATE_LEN 80 +#define STATE_SHORT_LEN_30MS 58 +#define STATE_SHORT_LEN_20MS 57 + +/* LPC settings */ + +#define LPC_FILTERORDER 10 +#define LPC_CHIRP_SYNTDENUM (float)0.9025 +#define LPC_CHIRP_WEIGHTDENUM (float)0.4222 +#define LPC_LOOKBACK 60 +#define LPC_N_20MS 1 +#define LPC_N_30MS 2 +#define LPC_N_MAX 2 +#define LPC_ASYMDIFF 20 +#define LPC_BW (float)60.0 +#define LPC_WN (float)1.0001 +#define LSF_NSPLIT 3 + +#define LSF_NUMBER_OF_STEPS 4 +#define LPC_HALFORDER (LPC_FILTERORDER/2) + +/* cb settings */ + +#define CB_NSTAGES 3 +#define CB_EXPAND 2 +#define CB_MEML 147 +#define CB_FILTERLEN 2*4 +#define CB_HALFFILTERLEN 4 +#define CB_RESRANGE 34 +#define CB_MAXGAIN (float)1.3 + +/* enhancer */ + +#define ENH_BLOCKL 80 /* block length */ +#define ENH_BLOCKL_HALF (ENH_BLOCKL/2) +#define ENH_HL 3 /* 2*ENH_HL+1 is number blocks + in said second sequence */ +#define ENH_SLOP 2 /* max difference estimated and + correct pitch period */ +#define ENH_PLOCSL 20 /* pitch-estimates and pitch- + locations buffer length */ +#define ENH_OVERHANG 2 +#define ENH_UPS0 4 /* upsampling rate */ +#define ENH_FL0 3 /* 2*FLO+1 is the length of + each filter */ +#define ENH_VECTL (ENH_BLOCKL+2*ENH_FL0) +#define ENH_CORRDIM (2*ENH_SLOP+1) +#define ENH_NBLOCKS (BLOCKL_MAX/ENH_BLOCKL) +#define ENH_NBLOCKS_EXTRA 5 +#define ENH_NBLOCKS_TOT 8 /* ENH_NBLOCKS + + ENH_NBLOCKS_EXTRA */ +#define ENH_BUFL (ENH_NBLOCKS_TOT)*ENH_BLOCKL +#define ENH_ALPHA0 (float)0.05 + +/* Down sampling */ + +#define FILTERORDER_DS 7 +#define DELAY_DS 3 +#define FACTOR_DS 2 + +/* bit stream defs */ + +#define NO_OF_BYTES_20MS 38 +#define NO_OF_BYTES_30MS 50 +#define NO_OF_WORDS_20MS 19 +#define NO_OF_WORDS_30MS 25 +#define STATE_BITS 3 +#define BYTE_LEN 8 +#define ULP_CLASSES 3 + +/* help parameters */ + + +#define FLOAT_MAX (float)1.0e37 +#define EPS (float)2.220446049250313e-016 +#define PI (float)3.14159265358979323846 +#define MIN_SAMPLE -32768 +#define MAX_SAMPLE 32767 +#define TWO_PI (float)6.283185307 +#define PI2 (float)0.159154943 + +/* type definition encoder instance */ +typedef struct iLBC_ULP_Inst_t_ { + int lsf_bits[6][ULP_CLASSES+2]; + int start_bits[ULP_CLASSES+2]; + int startfirst_bits[ULP_CLASSES+2]; + int scale_bits[ULP_CLASSES+2]; + int state_bits[ULP_CLASSES+2]; + int extra_cb_index[CB_NSTAGES][ULP_CLASSES+2]; + int extra_cb_gain[CB_NSTAGES][ULP_CLASSES+2]; + int cb_index[NSUB_MAX][CB_NSTAGES][ULP_CLASSES+2]; + int cb_gain[NSUB_MAX][CB_NSTAGES][ULP_CLASSES+2]; +} iLBC_ULP_Inst_t; + +/* type definition encoder instance */ +typedef struct iLBC_Enc_Inst_t_ { + + /* flag for frame size mode */ + int mode; + + /* basic parameters for different frame sizes */ + int blockl; + int nsub; + int nasub; + int no_of_bytes, no_of_words; + int lpc_n; + int state_short_len; + const iLBC_ULP_Inst_t *ULP_inst; + + /* analysis filter state */ + float anaMem[LPC_FILTERORDER]; + + /* old lsf parameters for interpolation */ + float lsfold[LPC_FILTERORDER]; + float lsfdeqold[LPC_FILTERORDER]; + + /* signal buffer for LP analysis */ + float lpc_buffer[LPC_LOOKBACK + BLOCKL_MAX]; + + /* state of input HP filter */ + float hpimem[4]; + +} iLBC_Enc_Inst_t; + +/* type definition decoder instance */ +typedef struct iLBC_Dec_Inst_t_ { + + + /* flag for frame size mode */ + int mode; + + /* basic parameters for different frame sizes */ + int blockl; + int nsub; + int nasub; + int no_of_bytes, no_of_words; + int lpc_n; + int state_short_len; + const iLBC_ULP_Inst_t *ULP_inst; + + /* synthesis filter state */ + float syntMem[LPC_FILTERORDER]; + + /* old LSF for interpolation */ + float lsfdeqold[LPC_FILTERORDER]; + + /* pitch lag estimated in enhancer and used in PLC */ + int last_lag; + + /* PLC state information */ + int prevLag, consPLICount, prevPLI, prev_enh_pl; + float prevLpc[LPC_FILTERORDER+1]; + float prevResidual[NSUB_MAX*SUBL]; + float per; + unsigned long seed; + + /* previous synthesis filter parameters */ + float old_syntdenum[(LPC_FILTERORDER + 1)*NSUB_MAX]; + + /* state of output HP filter */ + float hpomem[4]; + + /* enhancer state information */ + int use_enhancer; + float enh_buf[ENH_BUFL]; + float enh_period[ENH_NBLOCKS_TOT]; + +} iLBC_Dec_Inst_t; + +#endif + + diff --git a/libs/codec/ilbc/iLBC_encode.c b/libs/codec/ilbc/iLBC_encode.c new file mode 100644 index 0000000000..e874242b35 --- /dev/null +++ b/libs/codec/ilbc/iLBC_encode.c @@ -0,0 +1,514 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + iLBC_encode.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include +#include +#include + +#include "iLBC_define.h" +#include "iLBC_encode.h" +#include "LPCencode.h" +#include "FrameClassify.h" +#include "StateSearchW.h" +#include "StateConstructW.h" +#include "helpfun.h" +#include "constants.h" +#include "packing.h" +#include "iCBSearch.h" +#include "iCBConstruct.h" +#include "hpInput.h" +#include "anaFilter.h" +#include "syntFilter.h" + +/*----------------------------------------------------------------* + * Initiation of encoder instance. + *---------------------------------------------------------------*/ + +short initEncode( /* (o) Number of bytes + encoded */ + iLBC_Enc_Inst_t *iLBCenc_inst, /* (i/o) Encoder instance */ + int mode /* (i) frame size mode */ +){ + iLBCenc_inst->mode = mode; + if (mode==30) { + iLBCenc_inst->blockl = BLOCKL_30MS; + iLBCenc_inst->nsub = NSUB_30MS; + + + iLBCenc_inst->nasub = NASUB_30MS; + iLBCenc_inst->lpc_n = LPC_N_30MS; + iLBCenc_inst->no_of_bytes = NO_OF_BYTES_30MS; + iLBCenc_inst->no_of_words = NO_OF_WORDS_30MS; + iLBCenc_inst->state_short_len=STATE_SHORT_LEN_30MS; + /* ULP init */ + iLBCenc_inst->ULP_inst=&ULP_30msTbl; + } + else if (mode==20) { + iLBCenc_inst->blockl = BLOCKL_20MS; + iLBCenc_inst->nsub = NSUB_20MS; + iLBCenc_inst->nasub = NASUB_20MS; + iLBCenc_inst->lpc_n = LPC_N_20MS; + iLBCenc_inst->no_of_bytes = NO_OF_BYTES_20MS; + iLBCenc_inst->no_of_words = NO_OF_WORDS_20MS; + iLBCenc_inst->state_short_len=STATE_SHORT_LEN_20MS; + /* ULP init */ + iLBCenc_inst->ULP_inst=&ULP_20msTbl; + } + else { + exit(2); + } + + memset((*iLBCenc_inst).anaMem, 0, + LPC_FILTERORDER*sizeof(float)); + memcpy((*iLBCenc_inst).lsfold, lsfmeanTbl, + LPC_FILTERORDER*sizeof(float)); + memcpy((*iLBCenc_inst).lsfdeqold, lsfmeanTbl, + LPC_FILTERORDER*sizeof(float)); + memset((*iLBCenc_inst).lpc_buffer, 0, + (LPC_LOOKBACK+BLOCKL_MAX)*sizeof(float)); + memset((*iLBCenc_inst).hpimem, 0, 4*sizeof(float)); + + return (iLBCenc_inst->no_of_bytes); +} + +/*----------------------------------------------------------------* + * main encoder function + *---------------------------------------------------------------*/ + +void iLBC_encode( + unsigned char *bytes, /* (o) encoded data bits iLBC */ + float *block, /* (o) speech vector to + encode */ + iLBC_Enc_Inst_t *iLBCenc_inst /* (i/o) the general encoder + state */ +){ + + float data[BLOCKL_MAX]; + float residual[BLOCKL_MAX], reverseResidual[BLOCKL_MAX]; + + int start, idxForMax, idxVec[STATE_LEN]; + float reverseDecresidual[BLOCKL_MAX], mem[CB_MEML]; + int n, k, meml_gotten, Nfor, Nback, i, pos; + + + int gain_index[CB_NSTAGES*NASUB_MAX], + extra_gain_index[CB_NSTAGES]; + int cb_index[CB_NSTAGES*NASUB_MAX],extra_cb_index[CB_NSTAGES]; + int lsf_i[LSF_NSPLIT*LPC_N_MAX]; + unsigned char *pbytes; + int diff, start_pos, state_first; + float en1, en2; + int index, ulp, firstpart; + int subcount, subframe; + float weightState[LPC_FILTERORDER]; + float syntdenum[NSUB_MAX*(LPC_FILTERORDER+1)]; + float weightdenum[NSUB_MAX*(LPC_FILTERORDER+1)]; + float decresidual[BLOCKL_MAX]; + + /* high pass filtering of input signal if such is not done + prior to calling this function */ + + hpInput(block, iLBCenc_inst->blockl, + data, (*iLBCenc_inst).hpimem); + + /* otherwise simply copy */ + + /*memcpy(data,block,iLBCenc_inst->blockl*sizeof(float));*/ + + /* LPC of hp filtered input data */ + + LPCencode(syntdenum, weightdenum, lsf_i, data, iLBCenc_inst); + + + /* inverse filter to get residual */ + + for (n=0; nnsub; n++) { + anaFilter(&data[n*SUBL], &syntdenum[n*(LPC_FILTERORDER+1)], + SUBL, &residual[n*SUBL], iLBCenc_inst->anaMem); + } + + /* find state location */ + + start = FrameClassify(iLBCenc_inst, residual); + + /* check if state should be in first or last part of the + two subframes */ + + diff = STATE_LEN - iLBCenc_inst->state_short_len; + en1 = 0; + index = (start-1)*SUBL; + for (i = 0; i < iLBCenc_inst->state_short_len; i++) { + en1 += residual[index+i]*residual[index+i]; + } + en2 = 0; + index = (start-1)*SUBL+diff; + for (i = 0; i < iLBCenc_inst->state_short_len; i++) { + en2 += residual[index+i]*residual[index+i]; + } + + + + + if (en1 > en2) { + state_first = 1; + start_pos = (start-1)*SUBL; + } else { + state_first = 0; + start_pos = (start-1)*SUBL + diff; + } + + /* scalar quantization of state */ + + StateSearchW(iLBCenc_inst, &residual[start_pos], + &syntdenum[(start-1)*(LPC_FILTERORDER+1)], + &weightdenum[(start-1)*(LPC_FILTERORDER+1)], &idxForMax, + idxVec, iLBCenc_inst->state_short_len, state_first); + + StateConstructW(idxForMax, idxVec, + &syntdenum[(start-1)*(LPC_FILTERORDER+1)], + &decresidual[start_pos], iLBCenc_inst->state_short_len); + + /* predictive quantization in state */ + + if (state_first) { /* put adaptive part in the end */ + + /* setup memory */ + + memset(mem, 0, + (CB_MEML-iLBCenc_inst->state_short_len)*sizeof(float)); + memcpy(mem+CB_MEML-iLBCenc_inst->state_short_len, + decresidual+start_pos, + iLBCenc_inst->state_short_len*sizeof(float)); + memset(weightState, 0, LPC_FILTERORDER*sizeof(float)); + + /* encode sub-frames */ + + iCBSearch(iLBCenc_inst, extra_cb_index, extra_gain_index, + &residual[start_pos+iLBCenc_inst->state_short_len], + mem+CB_MEML-stMemLTbl, + stMemLTbl, diff, CB_NSTAGES, + &weightdenum[start*(LPC_FILTERORDER+1)], + weightState, 0); + + /* construct decoded vector */ + + iCBConstruct( + &decresidual[start_pos+iLBCenc_inst->state_short_len], + extra_cb_index, extra_gain_index, + mem+CB_MEML-stMemLTbl, + stMemLTbl, diff, CB_NSTAGES); + + } + else { /* put adaptive part in the beginning */ + + + + /* create reversed vectors for prediction */ + + for (k=0; kstate_short_len)]; + } + + /* setup memory */ + + meml_gotten = iLBCenc_inst->state_short_len; + for (k=0; knsub-start-1; + + + if ( Nfor > 0 ) { + + /* setup memory */ + + memset(mem, 0, (CB_MEML-STATE_LEN)*sizeof(float)); + memcpy(mem+CB_MEML-STATE_LEN, decresidual+(start-1)*SUBL, + STATE_LEN*sizeof(float)); + memset(weightState, 0, LPC_FILTERORDER*sizeof(float)); + + + + /* loop over sub-frames to encode */ + + for (subframe=0; subframe 0 ) { + + /* create reverse order vectors */ + + for (n=0; nnsub+1-start); + + + if ( meml_gotten > CB_MEML ) { + meml_gotten=CB_MEML; + } + for (k=0; klpc_n; k++) { + packsplit(&lsf_i[k], &firstpart, &lsf_i[k], + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp], + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp]+ + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp+1]+ + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp], &pos); + } + + /* Start block info */ + + packsplit(&start, &firstpart, &start, + iLBCenc_inst->ULP_inst->start_bits[ulp], + iLBCenc_inst->ULP_inst->start_bits[ulp]+ + iLBCenc_inst->ULP_inst->start_bits[ulp+1]+ + iLBCenc_inst->ULP_inst->start_bits[ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->start_bits[ulp], &pos); + + packsplit(&state_first, &firstpart, &state_first, + iLBCenc_inst->ULP_inst->startfirst_bits[ulp], + iLBCenc_inst->ULP_inst->startfirst_bits[ulp]+ + iLBCenc_inst->ULP_inst->startfirst_bits[ulp+1]+ + iLBCenc_inst->ULP_inst->startfirst_bits[ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->startfirst_bits[ulp], &pos); + + packsplit(&idxForMax, &firstpart, &idxForMax, + iLBCenc_inst->ULP_inst->scale_bits[ulp], + iLBCenc_inst->ULP_inst->scale_bits[ulp]+ + iLBCenc_inst->ULP_inst->scale_bits[ulp+1]+ + iLBCenc_inst->ULP_inst->scale_bits[ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->scale_bits[ulp], &pos); + + + + for (k=0; kstate_short_len; k++) { + packsplit(idxVec+k, &firstpart, idxVec+k, + iLBCenc_inst->ULP_inst->state_bits[ulp], + iLBCenc_inst->ULP_inst->state_bits[ulp]+ + iLBCenc_inst->ULP_inst->state_bits[ulp+1]+ + iLBCenc_inst->ULP_inst->state_bits[ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->state_bits[ulp], &pos); + } + + /* 23/22 (20ms/30ms) sample block */ + + for (k=0;kULP_inst->extra_cb_index[k][ulp], + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp]+ + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp+1]+ + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp], + &pos); + } + + for (k=0;kULP_inst->extra_cb_gain[k][ulp], + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp]+ + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp+1]+ + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp], + &pos); + } + + /* The two/four (20ms/30ms) 40 sample sub-blocks */ + + for (i=0; inasub; i++) { + for (k=0; kULP_inst->cb_index[i][k][ulp], + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp]+ + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp+1]+ + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp], + &pos); + } + } + + for (i=0; inasub; i++) { + for (k=0; kULP_inst->cb_gain[i][k][ulp], + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp]+ + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp+1]+ + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp+2]); + dopack( &pbytes, firstpart, + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp], + &pos); + } + } + } + + /* set the last bit to zero (otherwise the decoder + will treat it as a lost frame) */ + dopack( &pbytes, 0, 1, &pos); +} + + + diff --git a/libs/codec/ilbc/iLBC_encode.h b/libs/codec/ilbc/iLBC_encode.h new file mode 100644 index 0000000000..dc46790f0f --- /dev/null +++ b/libs/codec/ilbc/iLBC_encode.h @@ -0,0 +1,37 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + iLBC_encode.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#ifndef __iLBC_ILBCENCODE_H +#define __iLBC_ILBCENCODE_H + +#include "iLBC_define.h" + +short initEncode( /* (o) Number of bytes + encoded */ + iLBC_Enc_Inst_t *iLBCenc_inst, /* (i/o) Encoder instance */ + int mode /* (i) frame size mode */ +); + +void iLBC_encode( + + + unsigned char *bytes, /* (o) encoded data bits iLBC */ + float *block, /* (o) speech vector to + encode */ + iLBC_Enc_Inst_t *iLBCenc_inst /* (i/o) the general encoder + state */ +); + +#endif + + + diff --git a/libs/codec/ilbc/lsf.c b/libs/codec/ilbc/lsf.c new file mode 100644 index 0000000000..1be19da260 --- /dev/null +++ b/libs/codec/ilbc/lsf.c @@ -0,0 +1,264 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + lsf.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include +#include + +#include "iLBC_define.h" +#include "lsf.h" + +/*----------------------------------------------------------------* + * conversion from lpc coefficients to lsf coefficients + *---------------------------------------------------------------*/ + +void a2lsf( + float *freq,/* (o) lsf coefficients */ + float *a /* (i) lpc coefficients */ +){ + float steps[LSF_NUMBER_OF_STEPS] = + {(float)0.00635, (float)0.003175, (float)0.0015875, + (float)0.00079375}; + float step; + int step_idx; + int lsp_index; + float p[LPC_HALFORDER]; + float q[LPC_HALFORDER]; + float p_pre[LPC_HALFORDER]; + + + float q_pre[LPC_HALFORDER]; + float old_p, old_q, *old; + float *pq_coef; + float omega, old_omega; + int i; + float hlp, hlp1, hlp2, hlp3, hlp4, hlp5; + + for (i=0; i= 0.5)){ + + if (step_idx == (LSF_NUMBER_OF_STEPS - 1)){ + + if (fabs(hlp5) >= fabs(*old)) { + freq[lsp_index] = omega - step; + } else { + freq[lsp_index] = omega; + } + + + if ((*old) >= 0.0){ + *old = (float)-1.0 * FLOAT_MAX; + } else { + *old = FLOAT_MAX; + } + + omega = old_omega; + step_idx = 0; + + step_idx = LSF_NUMBER_OF_STEPS; + } else { + + if (step_idx == 0) { + old_omega = omega; + } + + step_idx++; + omega -= steps[step_idx]; + + /* Go back one grid step */ + + step = steps[step_idx]; + } + } else { + + /* increment omega until they are of different sign, + and we know there is at least one root between omega + and old_omega */ + *old = hlp5; + omega += step; + } + + + } + } + + for (i = 0; i= 0.5)){ + + + if (freq[0] <= 0.0) { + freq[0] = (float)0.022; + } + + + if (freq[LPC_FILTERORDER - 1] >= 0.5) { + freq[LPC_FILTERORDER - 1] = (float)0.499; + } + + hlp = (freq[LPC_FILTERORDER - 1] - freq[0]) / + (float) (LPC_FILTERORDER - 1); + + for (i=1; i +#include + +#include "iLBC_define.h" +#include "constants.h" +#include "helpfun.h" +#include "packing.h" +#include "string.h" + +/*----------------------------------------------------------------* + * splitting an integer into first most significant bits and + * remaining least significant bits + *---------------------------------------------------------------*/ + +void packsplit( + int *index, /* (i) the value to split */ + int *firstpart, /* (o) the value specified by most + significant bits */ + int *rest, /* (o) the value specified by least + significant bits */ + int bitno_firstpart, /* (i) number of bits in most + significant part */ + int bitno_total /* (i) number of bits in full range + of value */ +){ + int bitno_rest = bitno_total-bitno_firstpart; + + + + *firstpart = *index>>(bitno_rest); + *rest = *index-(*firstpart<<(bitno_rest)); +} + +/*----------------------------------------------------------------* + * combining a value corresponding to msb's with a value + * corresponding to lsb's + *---------------------------------------------------------------*/ + +void packcombine( + int *index, /* (i/o) the msb value in the + combined value out */ + int rest, /* (i) the lsb value */ + int bitno_rest /* (i) the number of bits in the + lsb part */ +){ + *index = *index<0) { + + /* Jump to the next byte if end of this byte is reached*/ + + if (*pos==8) { + *pos=0; + (*bitstream)++; + **bitstream=0; + } + + + + posLeft=8-(*pos); + + /* Insert index into the bitstream */ + + if (bitno <= posLeft) { + **bitstream |= (unsigned char)(index<<(posLeft-bitno)); + *pos+=bitno; + bitno=0; + } else { + **bitstream |= (unsigned char)(index>>(bitno-posLeft)); + + *pos=8; + index-=((index>>(bitno-posLeft))<<(bitno-posLeft)); + + bitno-=posLeft; + } + } +} + +/*----------------------------------------------------------------* + * unpacking of bits from bitstream, i.e., vector of bytes + *---------------------------------------------------------------*/ + +void unpack( + unsigned char **bitstream, /* (i/o) on entrance pointer to + place in bitstream to + unpack new data from, on + exit pointer to place in + bitstream to unpack future + data from */ + int *index, /* (o) resulting value */ + int bitno, /* (i) number of bits used to + represent the value */ + int *pos /* (i/o) read position in the + current byte */ +){ + int BitsLeft; + + *index=0; + + while (bitno>0) { + + /* move forward in bitstream when the end of the + byte is reached */ + + if (*pos==8) { + *pos=0; + (*bitstream)++; + } + + BitsLeft=8-(*pos); + + /* Extract bits to index */ + + + + if (BitsLeft>=bitno) { + *index+=((((**bitstream)<<(*pos)) & 0xFF)>>(8-bitno)); + + *pos+=bitno; + bitno=0; + } else { + + if ((8-bitno)>0) { + *index+=((((**bitstream)<<(*pos)) & 0xFF)>> + (8-bitno)); + *pos=8; + } else { + *index+=(((int)(((**bitstream)<<(*pos)) & 0xFF))<< + (bitno-8)); + *pos=8; + } + bitno-=BitsLeft; + } + } +} + + diff --git a/libs/codec/ilbc/packing.h b/libs/codec/ilbc/packing.h new file mode 100644 index 0000000000..77db258440 --- /dev/null +++ b/libs/codec/ilbc/packing.h @@ -0,0 +1,67 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + packing.h + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#ifndef __PACKING_H +#define __PACKING_H + +void packsplit( + int *index, /* (i) the value to split */ + int *firstpart, /* (o) the value specified by most + significant bits */ + int *rest, /* (o) the value specified by least + significant bits */ + int bitno_firstpart, /* (i) number of bits in most + significant part */ + int bitno_total /* (i) number of bits in full range + of value */ +); + +void packcombine( + int *index, /* (i/o) the msb value in the + combined value out */ + int rest, /* (i) the lsb value */ + int bitno_rest /* (i) the number of bits in the + lsb part */ +); + +void dopack( + unsigned char **bitstream, /* (i/o) on entrance pointer to + place in bitstream to pack + new data, on exit pointer + to place in bitstream to + pack future data */ + int index, /* (i) the value to pack */ + int bitno, /* (i) the number of bits that the + value will fit within */ + int *pos /* (i/o) write position in the + current byte */ +); + +void unpack( + unsigned char **bitstream, /* (i/o) on entrance pointer to + + + place in bitstream to + unpack new data from, on + exit pointer to place in + bitstream to unpack future + data from */ + int *index, /* (o) resulting value */ + int bitno, /* (i) number of bits used to + represent the value */ + int *pos /* (i/o) read position in the + current byte */ +); + +#endif + + diff --git a/libs/codec/ilbc/syntFilter.c b/libs/codec/ilbc/syntFilter.c new file mode 100644 index 0000000000..ff2e714c75 --- /dev/null +++ b/libs/codec/ilbc/syntFilter.c @@ -0,0 +1,108 @@ + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + syntFilter.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include "iLBC_define.h" +#include "syntFilter.h" + +/*----------------------------------------------------------------* + * LP synthesis filter. + *---------------------------------------------------------------*/ + +void syntFilter( + float *Out, /* (i/o) Signal to be filtered */ + float *a, /* (i) LP parameters */ + int len, /* (i) Length of signal */ + float *mem /* (i/o) Filter state */ +){ + int i, j; + float *po, *pi, *pa, *pm; + + po=Out; + + /* Filter first part using memory from past */ + + for (i=0; iinbuf[0]); + pebuf = &(st->pebuf[0]); + lpbuf = &(st->lpbuf[0]); + ivbuf = &(st->ivbuf[0]); + bias = &(st->bias); + osbuf = &(st->osbuf[0]); + osptr = &(st->osptr); + obound = &(st->obound[0]); + vwin = &(st->vwin[0]); + awin = &(st->awin[0]); + voibuf = &(st->voibuf[0]); + rmsbuf = &(st->rmsbuf[0]); + rcbuf = &(st->rcbuf[0]); + zpre = &(st->zpre); + + i__1 = 720 - contrl_1.lframe; + for (i__ = 181; i__ <= i__1; ++i__) { + inbuf[i__ - 181] = inbuf[contrl_1.lframe + i__ - 181]; + pebuf[i__ - 181] = pebuf[contrl_1.lframe + i__ - 181]; + } + i__1 = 540 - contrl_1.lframe; + for (i__ = 229; i__ <= i__1; ++i__) { + ivbuf[i__ - 229] = ivbuf[contrl_1.lframe + i__ - 229]; + } + i__1 = 720 - contrl_1.lframe; + for (i__ = 25; i__ <= i__1; ++i__) { + lpbuf[i__ - 25] = lpbuf[contrl_1.lframe + i__ - 25]; + } + j = 1; + i__1 = (*osptr) - 1; + for (i__ = 1; i__ <= i__1; ++i__) { + if (osbuf[i__ - 1] > contrl_1.lframe) { + osbuf[j - 1] = osbuf[i__ - 1] - contrl_1.lframe; + ++j; + } + } + *osptr = j; + voibuf[0] = voibuf[2]; + voibuf[1] = voibuf[3]; + for (i__ = 1; i__ <= 2; ++i__) { + vwin[(i__ << 1) - 2] = vwin[((i__ + 1) << 1) - 2] - contrl_1.lframe; + vwin[(i__ << 1) - 1] = vwin[((i__ + 1) << 1) - 1] - contrl_1.lframe; + awin[(i__ << 1) - 2] = awin[((i__ + 1) << 1) - 2] - contrl_1.lframe; + awin[(i__ << 1) - 1] = awin[((i__ + 1) << 1) - 1] - contrl_1.lframe; +/* EWIN(*,J) is unused for J .NE. AF, so the following shift is +*/ +/* unnecessary. It also causes error messages when the C versio +n */ +/* of the code created from this by f2c is run with Purify. It +*/ +/* correctly complains that uninitialized memory is being read. +*/ +/* EWIN(1,I) = EWIN(1,I+1) - LFRAME */ +/* EWIN(2,I) = EWIN(2,I+1) - LFRAME */ + obound[i__ - 1] = obound[i__]; + voibuf[i__ * 2] = voibuf[(i__ + 1) * 2]; + voibuf[(i__ << 1) + 1] = voibuf[((i__ + 1) << 1) + 1]; + rmsbuf[i__ - 1] = rmsbuf[i__]; + i__1 = contrl_1.order; + for (j = 1; j <= i__1; ++j) { + rcbuf[j + i__ * 10 - 11] = rcbuf[j + (i__ + 1) * 10 - 11]; + } + } +/* Copy input speech, scale to sign+12 bit integers */ +/* Remove long term DC bias. */ +/* If the average value in the frame was over 1/4096 (after current +*/ +/* BIAS correction), then subtract that much more from samples in */ +/* next frame. If the average value in the frame was under */ +/* -1/4096, add 1/4096 more to samples in next frame. In all other +*/ +/* cases, keep BIAS the same. */ + temp = 0.f; + i__1 = contrl_1.lframe; + for (i__ = 1; i__ <= i__1; ++i__) { + inbuf[720 - contrl_1.lframe + i__ - 181] = speech[i__] * 4096.f - + (*bias); + temp += inbuf[720 - contrl_1.lframe + i__ - 181]; + } + if (temp > (real) contrl_1.lframe) { + *bias += 1; + } + if (temp < (real) (-contrl_1.lframe)) { + *bias += -1; + } +/* Place Voicing Window */ + i__ = 721 - contrl_1.lframe; + preemp_(&inbuf[i__ - 181], &pebuf[i__ - 181], &contrl_1.lframe, &precoef, + zpre); + onset_(pebuf, osbuf, osptr, &c__10, &c__181, &c__720, &contrl_1.lframe, st); + +/* MAXOSP is just a debugging variable. */ + +/* MAXOSP = MAX( MAXOSP, OSPTR ) */ + + placev_(osbuf, osptr, &c__10, &obound[2], vwin, &c__3, &contrl_1.lframe, + &c__90, &c__156, &c__307, &c__462); +/* The Pitch Extraction algorithm estimates the pitch for a frame +*/ +/* of speech by locating the minimum of the average magnitude difference + */ +/* function (AMDF). The AMDF operates on low-pass, inverse filtered */ +/* speech. (The low-pass filter is an 800 Hz, 19 tap, equiripple, FIR +*/ +/* filter and the inverse filter is a 2nd-order LPC filter.) The pitch +*/ +/* estimate is later refined by dynamic programming (DYPTRK). However, +*/ +/* since some of DYPTRK's parameters are a function of the voicing */ +/* decisions, a voicing decision must precede the final pitch estimation. +*/ +/* See subroutines LPFILT, IVFILT, and TBDM. */ +/* LPFILT reads indices LBUFH-LFRAME-29 = 511 through LBUFH = 720 */ +/* of INBUF, and writes indices LBUFH+1-LFRAME = 541 through LBUFH +*/ +/* = 720 of LPBUF. */ + lpfilt_(&inbuf[228], &lpbuf[384], &c__312, &contrl_1.lframe); +/* IVFILT reads indices (PWINH-LFRAME-7) = 353 through PWINH = 540 +*/ +/* of LPBUF, and writes indices (PWINH-LFRAME+1) = 361 through */ +/* PWINH = 540 of IVBUF. */ + ivfilt_(&lpbuf[204], ivbuf, &c__312, &contrl_1.lframe, ivrc); +/* TBDM reads indices PWINL = 229 through */ +/* (PWINL-1)+MAXWIN+(TAU(LTAU)-TAU(1))/2 = 452 of IVBUF, and writes +*/ +/* indices 1 through LTAU = 60 of AMDF. */ + tbdm_(ivbuf, &c__156, tau, &c__60, amdf, &minptr, &maxptr, &mintau); +/* Voicing decisions are made for each half frame of input speech. +*/ +/* An initial voicing classification is made for each half of the */ +/* analysis frame, and the voicing decisions for the present frame */ +/* are finalized. See subroutine VOICIN. */ +/* The voicing detector (VOICIN) classifies the input signal as */ +/* unvoiced (including silence) or voiced using the AMDF windowed */ +/* maximum-to-minimum ratio, the zero crossing rate, energy measures, */ +/* reflection coefficients, and prediction gains. */ +/* The pitch and voicing rules apply smoothing and isolated */ +/* corrections to the pitch and voicing estimates and, in the process, +*/ +/* introduce two frames of delay into the corrected pitch estimates and +*/ +/* voicing decisions. */ + for (half = 1; half <= 2; ++half) { + voicin_(&vwin[4], inbuf, lpbuf, buflim, &half, &amdf[minptr - 1], & + amdf[maxptr - 1], &mintau, ivrc, obound, voibuf, &c__3, st); + } +/* Find the minimum cost pitch decision over several frames */ +/* given the current voicing decision and the AMDF array */ + dyptrk_(amdf, &c__60, &minptr, &voibuf[7], pitch, &midx, st); + ipitch = tau[midx - 1]; +/* Place spectrum analysis and energy windows */ + placea_(&ipitch, voibuf, &obound[2], &c__3, vwin, awin, ewin, & + contrl_1.lframe, &c__156); +/* Remove short term DC bias over the analysis window, Put result in ABUF +*/ + lanal = awin[5] + 1 - awin[4]; + dcbias_(&lanal, &pebuf[awin[4] - 181], abuf); +/* ABUF(1:LANAL) is now defined. It is equal to */ +/* PEBUF(AWIN(1,AF):AWIN(2,AF)) corrected for short term DC bias. */ +/* Compute RMS over integer number of pitch periods within the */ +/* analysis window. */ +/* Note that in a hardware implementation this computation may be */ +/* simplified by using diagonal elements of PHI computed by MLOAD. */ + i__1 = ewin[5] - ewin[4] + 1; + energy_(&i__1, &abuf[ewin[4] - awin[4]], &rmsbuf[2]); +/* Matrix load and invert, check RC's for stability */ + mload_(&contrl_1.order, &c__1, &lanal, abuf, phi, psi); + invert_(&contrl_1.order, phi, psi, &rcbuf[20]); + rcchk_(&contrl_1.order, &rcbuf[10], &rcbuf[20]); +/* Set return parameters */ + voice[1] = voibuf[2]; + voice[2] = voibuf[3]; + *rms = rmsbuf[0]; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + rc[i__] = rcbuf[i__ - 1]; + } + return 0; +} /* analys_ */ diff --git a/libs/codec/lpc10/bsynz.c b/libs/codec/lpc10/bsynz.c new file mode 100644 index 0000000000..e4810de222 --- /dev/null +++ b/libs/codec/lpc10/bsynz.c @@ -0,0 +1,447 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:18:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:58 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int bsynz_(real *coef, integer *ip, integer *iv, real *sout, real *rms, real *ratio, real *g2pass, struct lpc10_decoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: random_ 4 0 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* ***************************************************************** */ + +/* BSYNZ Version 54 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:18:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:58 jaf + * Initial revision + * */ +/* Revision 1.4 1996/03/27 18:11:22 jaf */ +/* Changed the range of NOISE printed out in the debugging statements, */ +/* even though they are commented out. I didn't discover this until I */ +/* tried comparing two different versions of the LPC-10 coder, each with */ +/* full tracing enabled. */ + +/* Revision 1.3 1996/03/26 19:33:23 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.2 1996/03/20 17:12:54 jaf */ +/* Added comments about which indices of array arguments are read or */ +/* written. */ + +/* Rearranged local variable declarations to indicate which need to be */ +/* saved from one invocation to the next. Added entry INITBSYNZ to */ +/* reinitialize the local state variables, if desired. */ + +/* Revision 1.1 1996/02/07 14:43:15 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Synthesize One Pitch Epoch */ + +/* Input: */ +/* COEF - Predictor coefficients */ +/* Indices 1 through ORDER read. */ +/* IP - Pitch period (number of samples to synthesize) */ +/* IV - Voicing for the current epoch */ +/* RMS - Energy for the current epoch */ +/* RATIO - Energy slope for plosives */ +/* G2PASS- Sharpening factor for 2 pass synthesis */ +/* Output: */ +/* SOUT - Synthesized speech */ +/* Indices 1 through IP written. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITBSYNZ. */ + +/* Subroutine */ int bsynz_(real *coef, integer *ip, integer *iv, + real *sout, real *rms, real *ratio, real *g2pass, + struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + integer *ipo; + real *rmso; + static integer kexc[25] = { 8,-16,26,-48,86,-162,294,-502,718,-728,184, + 672,-610,-672,184,728,718,502,294,162,86,48,26,16,8 }; + real *exc; + real *exc2; + real *lpi1; + real *lpi2; + real *lpi3; + real *hpi1; + real *hpi2; + real *hpi3; + + /* System generated locals */ + integer i__1, i__2; + real r__1, r__2; + + /* Builtin functions */ + double sqrt(doublereal); + + /* Local variables */ + real gain, xssq; + integer i__, j, k; + real noise[166], pulse; + integer px; + real sscale; + extern integer random_(struct lpc10_decoder_state *); + real xy, sum, ssq; + real lpi0, hpi0; + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:18:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:58 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:18:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:58 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Function return value definitions */ +/* Parameters/constants */ +/* KEXC is not a Fortran PARAMETER, but it is an array initialized +*/ +/* with a DATA statement that is never modified. */ +/* Local variables that need not be saved */ +/* NOISE is declared with range (1:MAXPIT+MAXORD), but only indices +*/ +/* ORDER+1 through ORDER+IP are ever used, and I think that IP */ +/* .LE. MAXPIT. Why not declare it to be in the range (1:MAXPIT) */ +/* and use that range? */ +/* Local state */ +/* I believe that only indices 1 through ORDER of EXC need to be */ +/* saved from one invocation to the next, but we may as well save */ +/* the whole array. */ +/* None of these local variables were given initial values in the */ +/* original code. I'm guessing that 0 is a reasonable initial */ +/* value for all of them. */ + /* Parameter adjustments */ + if (coef) { + --coef; + } + if (sout) { + --sout; + } + + /* Function Body */ + ipo = &(st->ipo); + exc = &(st->exc[0]); + exc2 = &(st->exc2[0]); + lpi1 = &(st->lpi1); + lpi2 = &(st->lpi2); + lpi3 = &(st->lpi3); + hpi1 = &(st->hpi1); + hpi2 = &(st->hpi2); + hpi3 = &(st->hpi3); + rmso = &(st->rmso_bsynz); + +/* MAXPIT+MAXORD=166 */ +/* Calculate history scale factor XY and scale filter state */ +/* Computing MIN */ + r__1 = *rmso / (*rms + 1e-6f); + xy = min(r__1,8.f); + *rmso = *rms; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + exc2[i__ - 1] = exc2[*ipo + i__ - 1] * xy; + } + *ipo = *ip; + if (*iv == 0) { +/* Generate white noise for unvoiced */ + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + exc[contrl_1.order + i__ - 1] = (real) (random_(st) / 64); + } +/* Impulse doublet excitation for plosives */ +/* (RANDOM()+32768) is in the range 0 to 2**16-1. Therefore the + */ +/* following expression should be evaluated using integers with +at */ +/* least 32 bits (16 isn't enough), and PX should be in the rang +e */ +/* ORDER+1+0 through ORDER+1+(IP-2) .EQ. ORDER+IP-1. */ + px = (random_(st) + 32768) * (*ip - 1) / 65536 + contrl_1.order + 1; + r__1 = *ratio / 4 * 1.f; + pulse = r__1 * 342; + if (pulse > 2e3f) { + pulse = 2e3f; + } + exc[px - 1] += pulse; + exc[px] -= pulse; +/* Load voiced excitation */ + } else { + sscale = sqrt((real) (*ip)) / 6.928f; + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + exc[contrl_1.order + i__ - 1] = 0.f; + if (i__ <= 25) { + exc[contrl_1.order + i__ - 1] = sscale * kexc[i__ - 1]; + } + lpi0 = exc[contrl_1.order + i__ - 1]; + r__2 = exc[contrl_1.order + i__ - 1] * .125f + *lpi1 * .75f; + r__1 = r__2 + *lpi2 * .125f; + exc[contrl_1.order + i__ - 1] = r__1 + *lpi3 * 0.f; + *lpi3 = *lpi2; + *lpi2 = *lpi1; + *lpi1 = lpi0; + } + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + noise[contrl_1.order + i__ - 1] = random_(st) * 1.f / 64; + hpi0 = noise[contrl_1.order + i__ - 1]; + r__2 = noise[contrl_1.order + i__ - 1] * -.125f + *hpi1 * .25f; + r__1 = r__2 + *hpi2 * -.125f; + noise[contrl_1.order + i__ - 1] = r__1 + *hpi3 * 0.f; + *hpi3 = *hpi2; + *hpi2 = *hpi1; + *hpi1 = hpi0; + } + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + exc[contrl_1.order + i__ - 1] += noise[contrl_1.order + i__ - 1]; + } + } +/* Synthesis filters: */ +/* Modify the excitation with all-zero filter 1 + G*SUM */ + xssq = 0.f; + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + k = contrl_1.order + i__; + sum = 0.f; + i__2 = contrl_1.order; + for (j = 1; j <= i__2; ++j) { + sum += coef[j] * exc[k - j - 1]; + } + sum *= *g2pass; + exc2[k - 1] = sum + exc[k - 1]; + } +/* Synthesize using the all pole filter 1 / (1 - SUM) */ + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + k = contrl_1.order + i__; + sum = 0.f; + i__2 = contrl_1.order; + for (j = 1; j <= i__2; ++j) { + sum += coef[j] * exc2[k - j - 1]; + } + exc2[k - 1] = sum + exc2[k - 1]; + xssq += exc2[k - 1] * exc2[k - 1]; + } +/* Save filter history for next epoch */ + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + exc[i__ - 1] = exc[*ip + i__ - 1]; + exc2[i__ - 1] = exc2[*ip + i__ - 1]; + } +/* Apply gain to match RMS */ + r__1 = *rms * *rms; + ssq = r__1 * *ip; + gain = sqrt(ssq / xssq); + i__1 = *ip; + for (i__ = 1; i__ <= i__1; ++i__) { + sout[i__] = gain * exc2[contrl_1.order + i__ - 1]; + } + return 0; +} /* bsynz_ */ diff --git a/libs/codec/lpc10/chanwr.c b/libs/codec/lpc10/chanwr.c new file mode 100644 index 0000000000..2253e7b69c --- /dev/null +++ b/libs/codec/lpc10/chanwr.c @@ -0,0 +1,232 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:20:24 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Revision 1.1 1996/08/19 22:40:31 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +/* *********************************************************************** */ + +/* CHANL Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:20:24 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Revision 1.1 1996/08/19 22:40:31 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/21 15:14:57 jaf */ +/* Added comments about which indices of argument arrays are read or */ +/* written, and about the one bit of local state in CHANWR. CHANRD */ +/* has no local state. */ + +/* Revision 1.2 1996/03/13 18:55:10 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* Revision 1.1 1996/02/07 14:43:31 jaf */ +/* Initial revision */ + + +/* *********************************************************************** */ + +/* CHANWR: */ +/* Place quantized parameters into bitstream */ + +/* Input: */ +/* ORDER - Number of reflection coefficients (not really variable) */ +/* IPITV - Quantized pitch/voicing parameter */ +/* IRMS - Quantized energy parameter */ +/* IRC - Quantized reflection coefficients */ +/* Indices 1 through ORDER read. */ +/* Output: */ +/* IBITS - Serial bitstream */ +/* Indices 1 through 54 written. */ +/* Bit 54, the SYNC bit, alternates from one call to the next. */ + +/* Subroutine CHANWR maintains one bit of local state from one call to */ +/* the next, in the variable ISYNC. I believe that this one bit is only */ +/* intended to allow a receiver to resynchronize its interpretation of */ +/* the bit stream, by looking for which of the 54 bits alternates every */ +/* frame time. This is just a simple framing mechanism that is not */ +/* useful when other, higher overhead framing mechanisms are used to */ +/* transmit the coded frames. */ + +/* I'm not going to make an entry to reinitialize this bit, since it */ +/* doesn't help a receiver much to know whether the first sync bit is a 0 */ +/* or a 1. It needs to examine several frames in sequence to have */ +/* reasonably good assurance that its framing is correct. */ + + +/* CHANRD: */ +/* Reconstruct parameters from bitstream */ + +/* Input: */ +/* ORDER - Number of reflection coefficients (not really variable) */ +/* IBITS - Serial bitstream */ +/* Indices 1 through 53 read (SYNC bit is ignored). */ +/* Output: */ +/* IPITV - Quantized pitch/voicing parameter */ +/* IRMS - Quantized energy parameter */ +/* IRC - Quantized reflection coefficients */ +/* Indices 1 through ORDER written */ + +/* Entry CHANRD has no local state. */ + + + +/* IBITS is 54 bits of LPC data ordered as follows: */ +/* R1-0, R2-0, R3-0, P-0, A-0, */ +/* R1-1, R2-1, R3-1, P-1, A-1, */ +/* R1-2, R4-0, R3-2, A-2, P-2, R4-1, */ +/* R1-3, R2-2, R3-3, R4-2, A-3, */ +/* R1-4, R2-3, R3-4, R4-3, A-4, */ +/* P-3, R2-4, R7-0, R8-0, P-4, R4-4, */ +/* R5-0, R6-0, R7-1,R10-0, R8-1, */ +/* R5-1, R6-1, R7-2, R9-0, P-5, */ +/* R5-2, R6-2,R10-1, R8-2, P-6, R9-1, */ +/* R5-3, R6-3, R7-3, R9-2, R8-3, SYNC */ +/* Subroutine */ int chanwr_0_(int n__, integer *order, integer *ipitv, + integer *irms, integer *irc, integer *ibits, + struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + integer *isync; + static integer bit[10] = { 2,4,8,8,8,8,16,16,16,16 }; + static integer iblist[53] = { 13,12,11,1,2,13,12,11,1,2,13,10,11,2,1,10, + 13,12,11,10,2,13,12,11,10,2,1,12,7,6,1,10,9,8,7,4,6,9,8,7,5,1,9,8, + 4,6,1,5,9,8,7,5,6 }; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer itab[13], i__; + +/* Arguments */ +/* Parameters/constants */ +/* These arrays are not Fortran PARAMETER's, but they are defined */ +/* by DATA statements below, and their contents are never altered. +*/ +/* Local variables that need not be saved */ +/* Local state */ +/* ISYNC is only used by CHANWR, not by ENTRY CHANRD. */ + + /* Parameter adjustments */ + --irc; + --ibits; + + /* Function Body */ + switch(n__) { + case 1: goto L_chanrd; + } + + isync = &(st->isync); + +/* *********************************************************************** + */ +/* Place quantized parameters into bitstream */ +/* *********************************************************************** + */ +/* Place parameters into ITAB */ + itab[0] = *ipitv; + itab[1] = *irms; + itab[2] = 0; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + itab[i__ + 2] = irc[*order + 1 - i__] & 32767; + } +/* Put 54 bits into IBITS array */ + for (i__ = 1; i__ <= 53; ++i__) { + ibits[i__] = itab[iblist[i__ - 1] - 1] & 1; + itab[iblist[i__ - 1] - 1] /= 2; + } + ibits[54] = *isync & 1; + *isync = 1 - *isync; + return 0; +/* *********************************************************************** + */ +/* Reconstruct parameters from bitstream */ +/* *********************************************************************** + */ + +L_chanrd: +/* Reconstruct ITAB */ + for (i__ = 1; i__ <= 13; ++i__) { + itab[i__ - 1] = 0; + } + for (i__ = 1; i__ <= 53; ++i__) { + itab[iblist[54 - i__ - 1] - 1] = (itab[iblist[54 - i__ - 1] - 1] << 1) + + ibits[54 - i__]; + } +/* Sign extend RC's */ + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + if ((itab[i__ + 2] & bit[i__ - 1]) != 0) { + itab[i__ + 2] -= bit[i__ - 1] << 1; + } + } +/* Restore variables */ + *ipitv = itab[0]; + *irms = itab[1]; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + irc[i__] = itab[*order + 4 - i__ - 1]; + } + return 0; +} /* chanwr_ */ + +/* Subroutine */ int chanwr_(integer *order, integer *ipitv, integer *irms, + integer *irc, integer *ibits, struct lpc10_encoder_state *st) +{ + return chanwr_0_(0, order, ipitv, irms, irc, ibits, st); + } + +/* Subroutine */ int chanrd_(integer *order, integer *ipitv, integer *irms, + integer *irc, integer *ibits) +{ + return chanwr_0_(1, order, ipitv, irms, irc, ibits, 0); + } diff --git a/libs/codec/lpc10/dcbias.c b/libs/codec/lpc10/dcbias.c new file mode 100644 index 0000000000..b0908042ca --- /dev/null +++ b/libs/codec/lpc10/dcbias.c @@ -0,0 +1,107 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:40:23 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int dcbias_(integer *len, real *speech, real *sigout); +#endif + +/* ********************************************************************* */ + +/* DCBIAS Version 50 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:40:23 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/18 21:19:22 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:44:53 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:44:21 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Calculate and remove DC bias from buffer. */ + +/* Input: */ +/* LEN - Length of speech buffers */ +/* SPEECH - Input speech buffer */ +/* Indices 1 through LEN read. */ +/* Output: */ +/* SIGOUT - Output speech buffer */ +/* Indices 1 through LEN written */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int dcbias_(integer *len, real *speech, real *sigout) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + real bias; + integer i__; + +/* Arguments */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --sigout; + --speech; + + /* Function Body */ + bias = 0.f; + i__1 = *len; + for (i__ = 1; i__ <= i__1; ++i__) { + bias += speech[i__]; + } + bias /= *len; + i__1 = *len; + for (i__ = 1; i__ <= i__1; ++i__) { + sigout[i__] = speech[i__] - bias; + } + return 0; +} /* dcbias_ */ + diff --git a/libs/codec/lpc10/decode.c b/libs/codec/lpc10/decode.c new file mode 100644 index 0000000000..3ab77e6831 --- /dev/null +++ b/libs/codec/lpc10/decode.c @@ -0,0 +1,625 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.2 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:22:39 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:38 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int decode_(integer *ipitv, integer *irms, integer *irc, integer *voice, integer *pitch, real *rms, real *rc, struct lpc10_decoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: ham84_ 14 3 4 4 4 */ +/*:ref: median_ 4 3 4 4 4 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static integer c__2 = 2; + +/* ***************************************************************** */ + +/* DECODE Version 54 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.2 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:22:39 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:38 jaf + * Initial revision + * */ +/* Revision 1.5 1996/05/23 20:06:03 jaf */ +/* Assigned PITCH a "default" value on the first call, since otherwise it */ +/* would be left uninitialized. */ + +/* Revision 1.4 1996/03/26 19:35:18 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.3 1996/03/21 21:10:50 jaf */ +/* Added entry INITDECODE to reinitialize the local state of subroutine */ +/* DECODE. */ + +/* Revision 1.2 1996/03/21 21:04:50 jaf */ +/* Determined which local variables should be saved from one invocation */ +/* to the next, and guessed initial values for some that should have been */ +/* saved, but weren't given initial values. Many of the arrays are */ +/* "constants", and many local variables are only used if the "global" */ +/* variable CORRP is .TRUE. */ + +/* Added comments explaining which indices of array arguments are read or */ +/* written. */ + +/* Revision 1.1 1996/02/12 03:21:10 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* This subroutine provides error correction and decoding */ +/* for all LPC parameters */ + +/* Input: */ +/* IPITV - Index value of pitch */ +/* IRMS - Coded Energy */ +/* CORRP - Error correction: */ +/* If FALSE, parameters are decoded directly with no delay. If TRUE, */ +/* most important parameter bits are protected by Hamming code and */ +/* median smoothed. This requires an additional frame of delay. */ +/* Input/Output: */ +/* IRC - Coded Reflection Coefficients */ +/* Indices 1 through ORDER always read, then written. */ +/* Output: */ +/* VOICE - Half frame voicing decisions */ +/* Indices 1 through 2 written. */ +/* PITCH - Decoded pitch */ +/* RMS - Energy */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER written. */ + +/* NOTE: Zero RC's should be done more directly, but this would affect */ +/* coded parameter printout. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITDECODE. */ + +/* Subroutine */ int decode_(integer *ipitv, integer *irms, + integer *irc, integer *voice, integer *pitch, real *rms, real *rc, + struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + logical *first; + static integer ethrs = 2048; + static integer ethrs1 = 128; + static integer ethrs2 = 1024; + static integer ethrs3 = 2048; + static integer ivtab[32] = { 24960,24960,24960,24960,25480,25480,25483, + 25480,16640,1560,1560,1560,16640,1816,1563,1560,24960,24960,24859, + 24856,26001,25881,25915,25913,1560,1560,7800,3640,1561,1561,3643, + 3641 }; + static real corth[32] /* was [4][8] */ = { 32767.f,10.f,5.f,0.f, + 32767.f,8.f,4.f,0.f,32.f,6.4f,3.2f,0.f,32.f,6.4f,3.2f,0.f,32.f, + 11.2f,6.4f,0.f,32.f,11.2f,6.4f,0.f,16.f,5.6f,3.2f,0.f,16.f,5.6f, + 3.2f,0.f }; + static integer detau[128] = { 0,0,0,3,0,3,3,31,0,3,3,21,3,3,29,30,0,3,3, + 20,3,25,27,26,3,23,58,22,3,24,28,3,0,3,3,3,3,39,33,32,3,37,35,36, + 3,38,34,3,3,42,46,44,50,40,48,3,54,3,56,3,52,3,3,1,0,3,3,108,3,78, + 100,104,3,84,92,88,156,80,96,3,3,74,70,72,66,76,68,3,62,3,60,3,64, + 3,3,1,3,116,132,112,148,152,3,3,140,3,136,3,144,3,3,1,124,120,128, + 3,3,3,3,1,3,3,3,1,3,1,1,1 }; + static integer rmst[64] = { 1024,936,856,784,718,656,600,550,502,460,420, + 384,352,328,294,270,246,226,206,188,172,158,144,132,120,110,102, + 92,84,78,70,64,60,54,50,46,42,38,34,32,30,26,24,22,20,18,17,16,15, + 14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 }; + static integer detab7[32] = { 4,11,18,25,32,39,46,53,60,66,72,77,82,87,92, + 96,101,104,108,111,114,115,117,119,121,122,123,124,125,126,127, + 127 }; + static real descl[8] = { .6953f,.625f,.5781f,.5469f,.5312f,.5391f,.4688f, + .3828f }; + integer *ivp2h; + static integer deadd[8] = { 1152,-2816,-1536,-3584,-1280,-2432,768,-1920 } + ; + static integer qb[8] = { 511,511,1023,1023,1023,1023,2047,4095 }; + static integer nbit[10] = { 8,8,5,5,4,4,4,4,3,2 }; + static integer zrc[10] = { 0,0,0,0,0,3,0,2,0,0 }; + static integer bit[5] = { 2,4,8,16,32 }; + integer *iovoic; + integer *iavgp; + integer *iptold; + integer *erate; + integer *drc; + integer *dpit; + integer *drms; + + /* System generated locals */ + integer i__1, i__2; + + /* Builtin functions */ + integer pow_ii(integer *, integer *); + + /* Local variables */ + extern /* Subroutine */ int ham84_(integer *, integer *, integer *); + integer ipit, iout, i__, icorf, index, ivoic, ixcor, i1, i2, i4; + extern integer median_(integer *, integer *, integer *); + integer ishift, errcnt, lsb; + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.2 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:22:39 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:38 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.2 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:22:39 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:38 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Function return value definitions */ + +/* Parameters/constants */ + +/* The variables below that are not Fortran PARAMETER's are */ +/* initialized with DATA statements, and then never modified. */ +/* The following are used regardless of CORRP's value. */ + +/* DETAU, NBIT, QB, DEADD, DETAB7, RMST, DESCL */ + +/* The following are used only if CORRP is .TRUE. */ + +/* ETHRS, ETHRS1, ETHRS2, ETHRS3, IVTAB, BIT, CORTH, ZRC */ + +/* Local variables that need not be saved */ + +/* The following are used regardless of CORRP's value */ +/* The following are used only if CORRP is .TRUE. */ + +/* Local state */ + +/* The following are used regardless of CORRP's value */ +/* The following are used only if CORRP is .TRUE. */ +/* I am guessing the initial values for IVP2H, IOVOIC, DRC, DPIT, */ +/* and DRMS. They should be checked to see if they are reasonable. +*/ +/* I'm also guessing for ERATE, but I think 0 is the right initial +*/ +/* value. */ + /* Parameter adjustments */ + if (irc) { + --irc; + } + if (voice) { + --voice; + } + if (rc) { + --rc; + } + + /* Function Body */ + + iptold = &(st->iptold); + first = &(st->first); + ivp2h = &(st->ivp2h); + iovoic = &(st->iovoic); + iavgp = &(st->iavgp); + erate = &(st->erate); + drc = &(st->drc[0]); + dpit = &(st->dpit[0]); + drms = &(st->drms[0]); + +/* DATA statements for "constants" defined above. */ +/* IF (LISTL.GE.3) WRITE(FDEBUG,800) IPITV,IRMS,(IRC(J),J=1,ORDER) */ +/* 800 FORMAT(1X,' <>',T32,6X,I6,I5,T50,10I8) */ +/* If no error correction, do pitch and voicing then jump to decode */ + i4 = detau[*ipitv]; + if (! contrl_1.corrp) { + voice[1] = 1; + voice[2] = 1; + if (*ipitv <= 1) { + voice[1] = 0; + } + if (*ipitv == 0 || *ipitv == 2) { + voice[2] = 0; + } + *pitch = i4; + if (*pitch <= 4) { + *pitch = *iptold; + } + if (voice[1] == 1 && voice[2] == 1) { + *iptold = *pitch; + } + if (voice[1] != voice[2]) { + *pitch = *iptold; + } + goto L900; + } +/* Do error correction pitch and voicing */ + if (i4 > 4) { + dpit[0] = i4; + ivoic = 2; + *iavgp = (*iavgp * 15 + i4 + 8) / 16; + } else { + ivoic = i4; + dpit[0] = *iavgp; + } + drms[0] = *irms; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + drc[i__ * 3 - 3] = irc[i__]; + } +/* Determine index to IVTAB from V/UV decision */ +/* If error rate is high then use alternate table */ + index = (*ivp2h << 4) + (*iovoic << 2) + ivoic + 1; + i1 = ivtab[index - 1]; + ipit = i1 & 3; + icorf = i1 / 8; + if (*erate < ethrs) { + icorf /= 64; + } +/* Determine error rate: 4=high 1=low */ + ixcor = 4; + if (*erate < ethrs3) { + ixcor = 3; + } + if (*erate < ethrs2) { + ixcor = 2; + } + if (*erate < ethrs1) { + ixcor = 1; + } +/* Voice/unvoice decision determined from bits 0 and 1 of IVTAB */ + voice[1] = icorf / 2 & 1; + voice[2] = icorf & 1; +/* Skip decoding on first frame because present data not yet available */ + if (*first) { + *first = FALSE_; +/* Assign PITCH a "default" value on the first call, since */ +/* otherwise it would be left uninitialized. The two lines +*/ +/* below were copied from above, since it seemed like a */ +/* reasonable thing to do for the first call. */ + *pitch = i4; + if (*pitch <= 4) { + *pitch = *iptold; + } + goto L500; + } +/* If bit 4 of ICORF is set then correct RMS and RC(1) - RC(4). */ +/* Determine error rate and correct errors using a Hamming 8,4 code */ +/* during transition or unvoiced frame. If IOUT is negative, */ +/* more than 1 error occurred, use previous frame's parameters. */ + if ((icorf & bit[3]) != 0) { + errcnt = 0; + lsb = drms[1] & 1; + index = (drc[22] << 4) + drms[1] / 2; + ham84_(&index, &iout, &errcnt); + drms[1] = drms[2]; + if (iout >= 0) { + drms[1] = (iout << 1) + lsb; + } + for (i__ = 1; i__ <= 4; ++i__) { + if (i__ == 1) { + i1 = ((drc[25] & 7) << 1) + (drc[28] & 1); + } else { + i1 = drc[(9 - i__) * 3 - 2] & 15; + } + i2 = drc[(5 - i__) * 3 - 2] & 31; + lsb = i2 & 1; + index = (i1 << 4) + i2 / 2; + ham84_(&index, &iout, &errcnt); + if (iout >= 0) { + iout = (iout << 1) + lsb; + if ((iout & 16) == 16) { + iout += -32; + } + } else { + iout = drc[(5 - i__) * 3 - 1]; + } + drc[(5 - i__) * 3 - 2] = iout; + } +/* Determine error rate */ + *erate = *erate * .96875f + errcnt * 102; + } +/* Get unsmoothed RMS, RC's, and PITCH */ + *irms = drms[1]; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + irc[i__] = drc[i__ * 3 - 2]; + } + if (ipit == 1) { + dpit[1] = dpit[2]; + } + if (ipit == 3) { + dpit[1] = dpit[0]; + } + *pitch = dpit[1]; +/* If bit 2 of ICORF is set then smooth RMS and RC's, */ + if ((icorf & bit[1]) != 0) { + if ((i__1 = drms[1] - drms[0], (real) abs(i__1)) >= corth[ixcor + 3] + && (i__2 = drms[1] - drms[2], (real) abs(i__2)) >= corth[ + ixcor + 3]) { + *irms = median_(&drms[2], &drms[1], drms); + } + for (i__ = 1; i__ <= 6; ++i__) { + if ((i__1 = drc[i__ * 3 - 2] - drc[i__ * 3 - 3], (real) abs(i__1)) + >= corth[ixcor + ((i__ + 2) << 2) - 5] && (i__2 = drc[i__ * + 3 - 2] - drc[i__ * 3 - 1], (real) abs(i__2)) >= corth[ + ixcor + ((i__ + 2) << 2) - 5]) { + irc[i__] = median_(&drc[i__ * 3 - 1], &drc[i__ * 3 - 2], &drc[ + i__ * 3 - 3]); + } + } + } +/* If bit 3 of ICORF is set then smooth pitch */ + if ((icorf & bit[2]) != 0) { + if ((i__1 = dpit[1] - dpit[0], (real) abs(i__1)) >= corth[ixcor - 1] + && (i__2 = dpit[1] - dpit[2], (real) abs(i__2)) >= corth[ + ixcor - 1]) { + *pitch = median_(&dpit[2], &dpit[1], dpit); + } + } +/* If bit 5 of ICORF is set then RC(5) - RC(10) are loaded with */ +/* values so that after quantization bias is removed in decode */ +/* the values will be zero. */ +L500: + if ((icorf & bit[4]) != 0) { + i__1 = contrl_1.order; + for (i__ = 5; i__ <= i__1; ++i__) { + irc[i__] = zrc[i__ - 1]; + } + } +/* House keeping - one frame delay */ + *iovoic = ivoic; + *ivp2h = voice[2]; + dpit[2] = dpit[1]; + dpit[1] = dpit[0]; + drms[2] = drms[1]; + drms[1] = drms[0]; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + drc[i__ * 3 - 1] = drc[i__ * 3 - 2]; + drc[i__ * 3 - 2] = drc[i__ * 3 - 3]; + } +L900: +/* IF (LISTL.GE.3)WRITE(FDEBUG,801)VOICE,PITCH,IRMS,(IRC(J),J=1,ORDER) */ +/* 801 FORMAT(1X,'<>',T32,2I3,I6,I5,T50,10I8) */ +/* Decode RMS */ + *irms = rmst[(31 - *irms) * 2]; +/* Decode RC(1) and RC(2) from log-area-ratios */ +/* Protect from illegal coded value (-16) caused by bit errors */ + for (i__ = 1; i__ <= 2; ++i__) { + i2 = irc[i__]; + i1 = 0; + if (i2 < 0) { + i1 = 1; + i2 = -i2; + if (i2 > 15) { + i2 = 0; + } + } + i2 = detab7[i2 * 2]; + if (i1 == 1) { + i2 = -i2; + } + ishift = 15 - nbit[i__ - 1]; + irc[i__] = i2 * pow_ii(&c__2, &ishift); + } +/* Decode RC(3)-RC(10) to sign plus 14 bits */ + i__1 = contrl_1.order; + for (i__ = 3; i__ <= i__1; ++i__) { + i2 = irc[i__]; + ishift = 15 - nbit[i__ - 1]; + i2 *= pow_ii(&c__2, &ishift); + i2 += qb[i__ - 3]; + irc[i__] = i2 * descl[i__ - 3] + deadd[i__ - 3]; + } +/* IF (LISTL.GE.3) WRITE(FDEBUG,811) IRMS, (IRC(I),I=1,ORDER) */ +/* 811 FORMAT(1X,'<>',T45,I4,1X,10I8) */ +/* Scale RMS and RC's to reals */ + *rms = (real) (*irms); + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + rc[i__] = irc[i__] / 16384.f; + } + return 0; +} /* decode_ */ diff --git a/libs/codec/lpc10/deemp.c b/libs/codec/lpc10/deemp.c new file mode 100644 index 0000000000..e6715e8c54 --- /dev/null +++ b/libs/codec/lpc10/deemp.c @@ -0,0 +1,154 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:23:46 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:34 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int deemp_(real *x, integer *n, struct lpc10_decoder_state *st); +#endif + +/* ***************************************************************** */ + +/* DEEMP Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:23:46 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:32:34 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/20 15:54:37 jaf */ +/* Added comments about which indices of array arguments are read or */ +/* written. */ + +/* Added entry INITDEEMP to reinitialize the local state variables, if */ +/* desired. */ + +/* Revision 1.2 1996/03/14 22:11:13 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* Revision 1.1 1996/02/07 14:44:53 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* De-Emphasize output speech with 1 / ( 1 - .75z**-1 ) */ +/* cascaded with 200 Hz high pass filter */ +/* ( 1 - 1.9998z**-1 + z**-2 ) / ( 1 - 1.75z**-1 + .78z**-2 ) */ + +/* WARNING! The coefficients above may be out of date with the code */ +/* below. Either that, or some kind of transformation was performed */ +/* on the coefficients above to create the code below. */ + +/* Input: */ +/* N - Number of samples */ +/* Input/Output: */ +/* X - Speech */ +/* Indices 1 through N are read before being written. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITDEEMP. */ + +/* Subroutine */ int deemp_(real *x, integer *n, struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + real *dei1; + real *dei2; + real *deo1; + real *deo2; + real *deo3; + + /* System generated locals */ + integer i__1; + real r__1; + + /* Local variables */ + integer k; + real dei0; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Local state */ +/* All of the locals saved below were not given explicit initial */ +/* values in the original code. I think 0 is a safe choice. */ + /* Parameter adjustments */ + if (x) { + --x; + } + + /* Function Body */ + + dei1 = &(st->dei1); + dei2 = &(st->dei2); + deo1 = &(st->deo1); + deo2 = &(st->deo2); + deo3 = &(st->deo3); + + i__1 = *n; + for (k = 1; k <= i__1; ++k) { + dei0 = x[k]; + r__1 = x[k] - *dei1 * 1.9998f + *dei2; + x[k] = r__1 + *deo1 * 2.5f - *deo2 * 2.0925f + *deo3 * .585f; + *dei2 = *dei1; + *dei1 = dei0; + *deo3 = *deo2; + *deo2 = *deo1; + *deo1 = x[k]; + } + return 0; +} /* deemp_ */ diff --git a/libs/codec/lpc10/difmag.c b/libs/codec/lpc10/difmag.c new file mode 100644 index 0000000000..03b12c3777 --- /dev/null +++ b/libs/codec/lpc10/difmag.c @@ -0,0 +1,133 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:14 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:31 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int difmag_(real *speech, integer *lpita, integer *tau, integer *ltau, integer *maxlag, real *amdf, integer *minptr, integer *maxptr); +#endif + +/* ********************************************************************** */ + +/* DIFMAG Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:14 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:32:31 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/15 23:09:39 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 14:41:31 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:45:04 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Compute Average Magnitude Difference Function */ + +/* Inputs: */ +/* SPEECH - Low pass filtered speech */ +/* Indices MIN_N1 through MAX_N1+LPITA-1 are read, where */ +/* MIN_N1 = (MAXLAG - MAX_TAU)/2+1 MAX_TAU = max of TAU(I) for I=1,LTAU +*/ +/* MAX_N1 = (MAXLAG - MIN_TAU)/2+1 MIN_TAU = min of TAU(I) for I=1,LTAU +*/ +/* LPITA - Length of speech buffer */ +/* TAU - Table of lags */ +/* Indices 1 through LTAU read. */ +/* LTAU - Number of lag values to compute */ +/* MAXLAG - Maximum possible lag value */ +/* Outputs: */ +/* (All of these outputs are also read, but only after being written.) */ +/* AMDF - Average Magnitude Difference for each lag in TAU */ +/* Indices 1 through LTAU written */ +/* MINPTR - Index of minimum AMDF value */ +/* MAXPTR - Index of maximum AMDF value */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int difmag_(real *speech, integer *lpita, integer *tau, + integer *ltau, integer *maxlag, real *amdf, integer *minptr, integer * + maxptr) +{ + /* System generated locals */ + integer i__1, i__2; + real r__1; + + /* Local variables */ + integer i__, j, n1, n2; + real sum; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Local state */ +/* None */ + /* Parameter adjustments */ + --amdf; + --tau; + --speech; + + /* Function Body */ + *minptr = 1; + *maxptr = 1; + i__1 = *ltau; + for (i__ = 1; i__ <= i__1; ++i__) { + n1 = (*maxlag - tau[i__]) / 2 + 1; + n2 = n1 + *lpita - 1; + sum = 0.f; + i__2 = n2; + for (j = n1; j <= i__2; j += 4) { + sum += (r__1 = speech[j] - speech[j + tau[i__]], abs(r__1)); + } + amdf[i__] = sum; + if (amdf[i__] < amdf[*minptr]) { + *minptr = i__; + } + if (amdf[i__] > amdf[*maxptr]) { + *maxptr = i__; + } + } + return 0; +} /* difmag_ */ + diff --git a/libs/codec/lpc10/dyptrk.c b/libs/codec/lpc10/dyptrk.c new file mode 100644 index 0000000000..4656b004e0 --- /dev/null +++ b/libs/codec/lpc10/dyptrk.c @@ -0,0 +1,405 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:25:29 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:26 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int dyptrk_(real *amdf, integer *ltau, integer *minptr, integer *voice, integer *pitch, integer *midx, struct lpc10_encoder_state *st); +/* comlen contrl_ 12 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* ********************************************************************* */ + +/* DYPTRK Version 52 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:25:29 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:26 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/26 19:35:35 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.4 1996/03/19 18:03:22 jaf */ +/* Replaced the initialization "DATA P/60*DEPTH*0/" with "DATA P/120*0/", */ +/* because apparently Fortran (or at least f2c) can't handle expressions */ +/* like that. */ + +/* Revision 1.3 1996/03/19 17:38:32 jaf */ +/* Added comments about the local variables that should be saved from one */ +/* invocation to the next. None of them were given initial values in the */ +/* original code, but from my testing, it appears that initializing them */ +/* all to 0 works. */ + +/* Added entry INITDYPTRK to reinitialize these local variables. */ + +/* Revision 1.2 1996/03/13 16:32:17 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* WARNING! Some of them that should are never given initial values in */ +/* this code. Hopefully, Fortran 77 defines initial values for them, but */ +/* even so, giving them explicit initial values is preferable. */ + +/* Revision 1.1 1996/02/07 14:45:14 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Dynamic Pitch Tracker */ + +/* Input: */ +/* AMDF - Average Magnitude Difference Function array */ +/* Indices 1 through LTAU read, and MINPTR */ +/* LTAU - Number of lags in AMDF */ +/* MINPTR - Location of minimum AMDF value */ +/* VOICE - Voicing decision */ +/* Output: */ +/* PITCH - Smoothed pitch value, 2 frames delayed */ +/* MIDX - Initial estimate of current frame pitch */ +/* Compile time constant: */ +/* DEPTH - Number of frames to trace back */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITDYPTRK. */ + +/* Subroutine */ int dyptrk_(real *amdf, integer *ltau, integer * + minptr, integer *voice, integer *pitch, integer *midx, + struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + real *s; + integer *p; + integer *ipoint; + real *alphax; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer pbar; + real sbar; + integer path[2], iptr, i__, j; + real alpha, minsc, maxsc; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:25:29 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:26 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Note that PATH is only used for debugging purposes, and can be */ +/* removed. */ +/* Local state */ +/* It would be a bit more "general" to define S(LTAU), if Fortran */ +/* allows the argument of a function to be used as the dimension of +*/ +/* a local array variable. */ +/* IPOINT is always in the range 0 to DEPTH-1. */ +/* WARNING! */ + +/* In the original version of this subroutine, IPOINT, ALPHAX, */ +/* every element of S, and potentially any element of P with the */ +/* second index value .NE. IPTR were read without being given */ +/* initial values (all indices of P with second index equal to */ +/* IPTR are all written before being read in this subroutine). */ + +/* From examining the code carefully, it appears that all of these +*/ +/* should be saved from one invocation to the next. */ + +/* I've run lpcsim with the "-l 6" option to see all of the */ +/* debugging information that is printed out by this subroutine */ +/* below, and it appears that S, P, IPOINT, and ALPHAX are all */ +/* initialized to 0 (these initial values would likely be different +*/ +/* on different platforms, compilers, etc.). Given that the output +*/ +/* of the coder sounds reasonable, I'm going to initialize these */ +/* variables to 0 explicitly. */ + + s = &(st->s[0]); + p = &(st->p[0]); + ipoint = &(st->ipoint); + alphax = &(st->alphax); + + + /* Parameter adjustments */ + if (amdf) { + --amdf; + } + + /* Function Body */ + +/* Calculate the confidence factor ALPHA, used as a threshold slope in +*/ +/* SEESAW. If unvoiced, set high slope so that every point in P array +*/ +/* is marked as a potential pitch frequency. A scaled up version (ALPHAX +)*/ +/* is used to maintain arithmetic precision. */ + if (*voice == 1) { + *alphax = *alphax * .75f + amdf[*minptr] / 2.f; + } else { + *alphax *= .984375f; + } + alpha = *alphax / 16; + if (*voice == 0 && *alphax < 128.f) { + alpha = 8.f; + } +/* SEESAW: Construct a pitch pointer array and intermediate winner functio +n*/ +/* Left to right pass: */ + iptr = *ipoint + 1; + p[iptr * 60 - 60] = 1; + i__ = 1; + pbar = 1; + sbar = s[0]; + i__1 = *ltau; + for (i__ = 1; i__ <= i__1; ++i__) { + sbar += alpha; + if (sbar < s[i__ - 1]) { + s[i__ - 1] = sbar; + p[i__ + iptr * 60 - 61] = pbar; + } else { + sbar = s[i__ - 1]; + p[i__ + iptr * 60 - 61] = i__; + pbar = i__; + } + } +/* Right to left pass: */ + i__ = pbar - 1; + sbar = s[i__]; + while(i__ >= 1) { + sbar += alpha; + if (sbar < s[i__ - 1]) { + s[i__ - 1] = sbar; + p[i__ + iptr * 60 - 61] = pbar; + } else { + pbar = p[i__ + iptr * 60 - 61]; + i__ = pbar; + sbar = s[i__ - 1]; + } + --i__; + } +/* Update S using AMDF */ +/* Find maximum, minimum, and location of minimum */ + s[0] += amdf[1] / 2; + minsc = s[0]; + maxsc = minsc; + *midx = 1; + i__1 = *ltau; + for (i__ = 2; i__ <= i__1; ++i__) { + s[i__ - 1] += amdf[i__] / 2; + if (s[i__ - 1] > maxsc) { + maxsc = s[i__ - 1]; + } + if (s[i__ - 1] < minsc) { + *midx = i__; + minsc = s[i__ - 1]; + } + } +/* Subtract MINSC from S to prevent overflow */ + i__1 = *ltau; + for (i__ = 1; i__ <= i__1; ++i__) { + s[i__ - 1] -= minsc; + } + maxsc -= minsc; +/* Use higher octave pitch if significant null there */ + j = 0; + for (i__ = 20; i__ <= 40; i__ += 10) { + if (*midx > i__) { + if (s[*midx - i__ - 1] < maxsc / 4) { + j = i__; + } + } + } + *midx -= j; +/* TRACE: look back two frames to find minimum cost pitch estimate */ + j = *ipoint; + *pitch = *midx; + for (i__ = 1; i__ <= 2; ++i__) { + j = j % 2 + 1; + *pitch = p[*pitch + j * 60 - 61]; + path[i__ - 1] = *pitch; + } + +/* The following statement subtracts one from IPOINT, mod DEPTH. I +*/ +/* think the author chose to add DEPTH-1, instead of subtracting 1, +*/ +/* because then it will work even if MOD doesn't work as desired on +*/ +/* negative arguments. */ + + *ipoint = (*ipoint + 1) % 2; + return 0; +} /* dyptrk_ */ diff --git a/libs/codec/lpc10/encode.c b/libs/codec/lpc10/encode.c new file mode 100644 index 0000000000..cfe1ef7991 --- /dev/null +++ b/libs/codec/lpc10/encode.c @@ -0,0 +1,373 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:21 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int encode_(integer *voice, integer *pitch, real *rms, real *rc, integer *ipitch, integer *irms, integer *irc); +/* comlen contrl_ 12 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static integer c__2 = 2; + +/* ***************************************************************** */ + +/* ENCODE Version 54 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:32:21 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/26 19:35:50 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.4 1996/03/21 00:26:29 jaf */ +/* Added the comment that this subroutine has no local state. */ + +/* In the last check-in, I forgot to mention that I had added comments */ +/* explaining which indices of array arguments are read or written. */ + +/* Revision 1.3 1996/03/21 00:22:39 jaf */ +/* Added comments explaining that all local arrays are effectively */ +/* constants. */ + +/* Revision 1.2 1996/03/13 18:48:33 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:45:29 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Quantize LPC parameters for transmission */ + +/* INPUTS: */ +/* VOICE - Half frame voicing decisions */ +/* Indices 1 through 2 read. */ +/* PITCH - Pitch */ +/* RMS - Energy */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER read. */ +/* CORRP - Error Correction: TRUE = yes, FALSE = none */ +/* (this is defined in file control.fh) */ +/* OUTPUTS: */ +/* IPITCH - Coded pitch and voicing */ +/* IRMS - Quantized energy */ +/* IRC - Quantized reflection coefficients */ +/* Indices 1 through MAX(ORDER,2) written. */ +/* If CORRP is .TRUE., then indices 1 through 10 written */ +/* for unvoiced frames. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int encode_(integer *voice, integer *pitch, real *rms, real * + rc, integer *ipitch, integer *irms, integer *irc) +{ + /* Initialized data */ + + static integer enctab[16] = { 0,7,11,12,13,10,6,1,14,9,5,2,3,4,8,15 }; + static integer entau[60] = { 19,11,27,25,29,21,23,22,30,14,15,7,39,38,46, + 42,43,41,45,37,53,49,51,50,54,52,60,56,58,26,90,88,92,84,86,82,83, + 81,85,69,77,73,75,74,78,70,71,67,99,97,113,112,114,98,106,104,108, + 100,101,76 }; + static integer enadd[8] = { 1920,-768,2432,1280,3584,1536,2816,-1152 }; + static real enscl[8] = { .0204f,.0167f,.0145f,.0147f,.0143f,.0135f,.0125f, + .0112f }; + static integer enbits[8] = { 6,5,4,4,4,4,3,3 }; + static integer entab6[64] = { 0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3, + 3,3,3,3,3,4,4,4,4,4,4,4,5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,9,9, + 9,10,10,11,11,12,13,14,15 }; + static integer rmst[64] = { 1024,936,856,784,718,656,600,550,502,460,420, + 384,352,328,294,270,246,226,206,188,172,158,144,132,120,110,102, + 92,84,78,70,64,60,54,50,46,42,38,34,32,30,26,24,22,20,18,17,16,15, + 14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 }; + + /* System generated locals */ + integer i__1, i__2; + + /* Builtin functions */ + integer pow_ii(integer *, integer *); + + /* Local variables */ + integer idel, nbit, i__, j, i2, i3, mrk; + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:32:21 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:32:21 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Parameters/constants */ +/* These arrays are not Fortran PARAMETER's, but they are defined */ +/* by DATA statements below, and their contents are never altered. +*/ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --irc; + --rc; + --voice; + + /* Function Body */ +/* Scale RMS and RC's to integers */ + *irms = *rms; + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { + irc[i__] = rc[i__] * 32768.f; + } +/* IF(LISTL.GE.3)WRITE(FDEBUG,800)VOICE,PITCH,IRMS,(IRC(I),I=1,ORDER) */ +/* 800 FORMAT(1X,/,' <>',T32,2I3,I6,I5,T50,10I8) */ +/* Encode pitch and voicing */ + if (voice[1] != 0 && voice[2] != 0) { + *ipitch = entau[*pitch - 1]; + } else { + if (contrl_1.corrp) { + *ipitch = 0; + if (voice[1] != voice[2]) { + *ipitch = 127; + } + } else { + *ipitch = (voice[1] << 1) + voice[2]; + } + } +/* Encode RMS by binary table search */ + j = 32; + idel = 16; + *irms = min(*irms,1023); + while(idel > 0) { + if (*irms > rmst[j - 1]) { + j -= idel; + } + if (*irms < rmst[j - 1]) { + j += idel; + } + idel /= 2; + } + if (*irms > rmst[j - 1]) { + --j; + } + *irms = 31 - j / 2; +/* Encode RC(1) and (2) as log-area-ratios */ + for (i__ = 1; i__ <= 2; ++i__) { + i2 = irc[i__]; + mrk = 0; + if (i2 < 0) { + i2 = -i2; + mrk = 1; + } + i2 /= 512; + i2 = min(i2,63); + i2 = entab6[i2]; + if (mrk != 0) { + i2 = -i2; + } + irc[i__] = i2; + } +/* Encode RC(3) - (10) linearly, remove bias then scale */ + i__1 = contrl_1.order; + for (i__ = 3; i__ <= i__1; ++i__) { + i2 = irc[i__] / 2; + i2 = (i2 + enadd[contrl_1.order + 1 - i__ - 1]) * enscl[ + contrl_1.order + 1 - i__ - 1]; +/* Computing MIN */ + i__2 = max(i2,-127); + i2 = min(i__2,127); + nbit = enbits[contrl_1.order + 1 - i__ - 1]; + i3 = 0; + if (i2 < 0) { + i3 = -1; + } + i2 /= pow_ii(&c__2, &nbit); + if (i3 == -1) { + --i2; + } + irc[i__] = i2; + } +/* Protect the most significant bits of the most */ +/* important parameters during non-voiced frames. */ +/* RC(1) - RC(4) are protected using 20 parity bits */ +/* replacing RC(5) - RC(10). */ + if (contrl_1.corrp) { + if (*ipitch == 0 || *ipitch == 127) { + irc[5] = enctab[(irc[1] & 30) / 2]; + irc[6] = enctab[(irc[2] & 30) / 2]; + irc[7] = enctab[(irc[3] & 30) / 2]; + irc[8] = enctab[(*irms & 30) / 2]; + irc[9] = enctab[(irc[4] & 30) / 2] / 2; + irc[10] = enctab[(irc[4] & 30) / 2] & 1; + } + } +/* IF(LISTL.GE.3)WRITE(FDEBUG,801)VOICE,IPITCH,IRMS,(IRC(J),J=1,ORDER) */ +/* 801 FORMAT(1X,'<>',T32,2I3,I6,I5,T50,10I8) */ + return 0; +} /* encode_ */ + diff --git a/libs/codec/lpc10/energy.c b/libs/codec/lpc10/energy.c new file mode 100644 index 0000000000..c5594b8bbf --- /dev/null +++ b/libs/codec/lpc10/energy.c @@ -0,0 +1,103 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:17 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int energy_(integer *len, real *speech, real *rms); +#endif + +/* ********************************************************************* */ + +/* ENERGY Version 50 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:32:17 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/18 21:17:41 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:46:02 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:45:40 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Compute RMS energy. */ + +/* Input: */ +/* LEN - Length of speech buffer */ +/* SPEECH - Speech buffer */ +/* Indices 1 through LEN read. */ +/* Output: */ +/* RMS - Root Mean Square energy */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int energy_(integer *len, real *speech, real *rms) +{ + /* System generated locals */ + integer i__1; + + /* Builtin functions */ + double sqrt(doublereal); + + /* Local variables */ + integer i__; + +/* Arguments */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --speech; + + /* Function Body */ + *rms = 0.f; + i__1 = *len; + for (i__ = 1; i__ <= i__1; ++i__) { + *rms += speech[i__] * speech[i__]; + } + *rms = sqrt(*rms / *len); + return 0; +} /* energy_ */ + diff --git a/libs/codec/lpc10/f2c.h b/libs/codec/lpc10/f2c.h new file mode 100644 index 0000000000..71946f04cb --- /dev/null +++ b/libs/codec/lpc10/f2c.h @@ -0,0 +1,325 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:26:28 jaf + * Any typedef defining a type that was used in lpc10_encoder_state or + * lpc10_decoder_state struct's was commented out here and added to + * lpc10.h. + * + * Revision 1.1 1996/08/19 22:32:13 jaf + * Initial revision + * + +*/ + +/* + * f2c.h + * + * SCCS ID: @(#)f2c.h 1.2 96/05/19 + */ + +/* f2c.h -- Standard Fortran to C header file */ + +/** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." + + - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */ + +#ifndef F2C_INCLUDE +#define F2C_INCLUDE + +#include "lpc10.h" + +/*typedef long int integer;*/ +/*typedef INT32 integer;*/ +/*typedef short int shortint;*/ +/*typedef INT16 shortint;*/ +/*typedef float real;*/ +/* doublereal only used for function arguments to sqrt, exp, etc. */ +typedef double doublereal; +/* 32 bits seems wasteful, but there really aren't that many logical + * variables around, and making them 32 bits could avoid word + * alignment problems, perhaps. */ +/*typedef long int logical;*/ +/*typedef INT32 logical;*/ +/* The following types are not used in the translated C code for the + * LPC-10 coder, but they might be needed by the definitions down + * below, so they don't cause compilation errors. */ +typedef char *address; +typedef struct { real r, i; } complex; +typedef struct { doublereal r, i; } doublecomplex; +typedef short int shortlogical; +typedef char logical1; +typedef char integer1; +/* typedef long long longint; */ /* system-dependent */ + +#define TRUE_ (1) +#define FALSE_ (0) + +/* Extern is for use with -E */ +#ifndef Extern +#define Extern extern +#endif + +/* I/O stuff */ + +#ifdef f2c_i2 +/* for -i2 */ +typedef short flag; +typedef short ftnlen; +typedef short ftnint; +#else +typedef long int flag; +typedef long int ftnlen; +typedef long int ftnint; +#endif + +/*external read, write*/ +typedef struct +{ flag cierr; + ftnint ciunit; + flag ciend; + char *cifmt; + ftnint cirec; +} cilist; + +/*internal read, write*/ +typedef struct +{ flag icierr; + char *iciunit; + flag iciend; + char *icifmt; + ftnint icirlen; + ftnint icirnum; +} icilist; + +/*open*/ +typedef struct +{ flag oerr; + ftnint ounit; + char *ofnm; + ftnlen ofnmlen; + char *osta; + char *oacc; + char *ofm; + ftnint orl; + char *oblnk; +} olist; + +/*close*/ +typedef struct +{ flag cerr; + ftnint cunit; + char *csta; +} cllist; + +/*rewind, backspace, endfile*/ +typedef struct +{ flag aerr; + ftnint aunit; +} alist; + +/* inquire */ +typedef struct +{ flag inerr; + ftnint inunit; + char *infile; + ftnlen infilen; + ftnint *inex; /*parameters in standard's order*/ + ftnint *inopen; + ftnint *innum; + ftnint *innamed; + char *inname; + ftnlen innamlen; + char *inacc; + ftnlen inacclen; + char *inseq; + ftnlen inseqlen; + char *indir; + ftnlen indirlen; + char *infmt; + ftnlen infmtlen; + char *inform; + ftnint informlen; + char *inunf; + ftnlen inunflen; + ftnint *inrecl; + ftnint *innrec; + char *inblank; + ftnlen inblanklen; +} inlist; + +#define VOID void + +union Multitype { /* for multiple entry points */ + integer1 g; + shortint h; + integer i; + /* longint j; */ + real r; + doublereal d; + complex c; + doublecomplex z; + }; + +typedef union Multitype Multitype; + +/*typedef long int Long;*/ /* No longer used; formerly in Namelist */ + +struct Vardesc { /* for Namelist */ + char *name; + char *addr; + ftnlen *dims; + int type; + }; +typedef struct Vardesc Vardesc; + +struct Namelist { + char *name; + Vardesc **vars; + int nvars; + }; +typedef struct Namelist Namelist; + +#define abs(x) ((x) >= 0 ? (x) : -(x)) +#define dabs(x) (doublereal)abs(x) +#define min(a,b) ((a) <= (b) ? (a) : (b)) +#define max(a,b) ((a) >= (b) ? (a) : (b)) +#define dmin(a,b) (doublereal)min(a,b) +#define dmax(a,b) (doublereal)max(a,b) + +/* procedure parameter types for -A and -C++ */ + +#define F2C_proc_par_types 1 +#ifdef __cplusplus +typedef int /* Unknown procedure type */ (*U_fp)(...); +typedef shortint (*J_fp)(...); +typedef integer (*I_fp)(...); +typedef real (*R_fp)(...); +typedef doublereal (*D_fp)(...), (*E_fp)(...); +typedef /* Complex */ VOID (*C_fp)(...); +typedef /* Double Complex */ VOID (*Z_fp)(...); +typedef logical (*L_fp)(...); +typedef shortlogical (*K_fp)(...); +typedef /* Character */ VOID (*H_fp)(...); +typedef /* Subroutine */ int (*S_fp)(...); +#else +typedef int /* Unknown procedure type */ (*U_fp)(VOID); +typedef shortint (*J_fp)(VOID); +typedef integer (*I_fp)(VOID); +typedef real (*R_fp)(VOID); +typedef doublereal (*D_fp)(VOID), (*E_fp)(VOID); +typedef /* Complex */ VOID (*C_fp)(VOID); +typedef /* Double Complex */ VOID (*Z_fp)(VOID); +typedef logical (*L_fp)(VOID); +typedef shortlogical (*K_fp)(VOID); +typedef /* Character */ VOID (*H_fp)(VOID); +typedef /* Subroutine */ int (*S_fp)(VOID); +#endif +/* E_fp is for real functions when -R is not specified */ +typedef VOID C_f; /* complex function */ +typedef VOID H_f; /* character function */ +typedef VOID Z_f; /* double complex function */ +typedef doublereal E_f; /* real function with -R not specified */ + +/* undef any lower-case symbols that your C compiler predefines, e.g.: */ + +#ifndef Skip_f2c_Undefs +#undef cray +#undef gcos +#undef mc68010 +#undef mc68020 +#undef mips +#undef pdp11 +#undef sgi +#undef sparc +#undef sun +#undef sun2 +#undef sun3 +#undef sun4 +#undef u370 +#undef u3b +#undef u3b2 +#undef u3b5 +#undef unix +#undef vax +#endif + +#ifdef KR_headers +extern integer pow_ii(ap, bp); +extern double r_sign(a,b); +extern integer i_nint(x); +#else +extern integer pow_ii(integer *ap, integer *bp); +extern double r_sign(real *a, real *b); +extern integer i_nint(real *x); + +#endif +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int bsynz_(real *coef, integer *ip, integer *iv, + real *sout, real *rms, real *ratio, real *g2pass, + struct lpc10_decoder_state *st); +extern int chanwr_(integer *order, integer *ipitv, integer *irms, + integer *irc, integer *ibits, struct lpc10_encoder_state *st); +extern int chanrd_(integer *order, integer *ipitv, integer *irms, + integer *irc, integer *ibits); +extern int chanwr_0_(int n__, integer *order, integer *ipitv, + integer *irms, integer *irc, integer *ibits, + struct lpc10_encoder_state *st); +extern int dcbias_(integer *len, real *speech, real *sigout); +extern int decode_(integer *ipitv, integer *irms, integer *irc, + integer *voice, integer *pitch, real *rms, + real *rc, struct lpc10_decoder_state *st); +extern int deemp_(real *x, integer *n, struct lpc10_decoder_state *st); +extern int difmag_(real *speech, integer *lpita, integer *tau, integer *ltau, + integer *maxlag, real *amdf, integer *minptr, integer *maxptr); +extern int dyptrk_(real *amdf, integer *ltau, integer * + minptr, integer *voice, integer *pitch, integer *midx, + struct lpc10_encoder_state *st); +extern int encode_(integer *voice, integer *pitch, real *rms, real *rc, + integer *ipitch, integer *irms, integer *irc); +extern int energy_(integer *len, real *speech, real *rms); +extern int ham84_(integer *input, integer *output, integer *errcnt); +extern int hp100_(real *speech, integer *start, integer *end, + struct lpc10_encoder_state *st); +extern int inithp100_(void); +extern int invert_(integer *order, real *phi, real *psi, real *rc); +extern int irc2pc_(real *rc, real *pc, integer *order, real *gprime, real *g2pass); +extern int ivfilt_(real *lpbuf, real *ivbuf, integer *len, integer *nsamp, real *ivrc); +extern int lpcdec_(integer *bits, real *speech); +extern int initlpcdec_(void); +extern int lpcenc_(real *speech, integer *bits); +extern int initlpcenc_(void); +extern int lpfilt_(real *inbuf, real *lpbuf, integer *len, integer *nsamp); +extern integer median_(integer *d1, integer *d2, integer *d3); +extern int mload_(integer *order, integer *awins, integer *awinf, real *speech, real *phi, real *psi); +extern int onset_(real *pebuf, integer *osbuf, integer *osptr, integer *oslen, integer *sbufl, integer *sbufh, integer *lframe, struct lpc10_encoder_state *st); +extern int pitsyn_(integer *order, integer *voice, integer *pitch, real *rms, real *rc, integer *lframe, integer *ivuv, integer *ipiti, real *rmsi, real *rci, integer *nout, real *ratio, struct lpc10_decoder_state *st); +extern int placea_(integer *ipitch, integer *voibuf, integer *obound, integer *af, integer *vwin, integer *awin, integer *ewin, integer *lframe, integer *maxwin); +extern int placev_(integer *osbuf, integer *osptr, integer *oslen, integer *obound, integer *vwin, integer *af, integer *lframe, integer *minwin, integer *maxwin, integer *dvwinl, integer *dvwinh); +extern int preemp_(real *inbuf, real *pebuf, integer *nsamp, real *coef, real *z__); +extern int prepro_(real *speech, integer *length, + struct lpc10_encoder_state *st); +extern int decode_(integer *ipitv, integer *irms, integer *irc, integer *voice, integer *pitch, real *rms, real *rc, struct lpc10_decoder_state *st); +extern integer random_(struct lpc10_decoder_state *st); +extern int rcchk_(integer *order, real *rc1f, real *rc2f); +extern int synths_(integer *voice, integer *pitch, real *rms, real *rc, real *speech, integer *k, struct lpc10_decoder_state *st); +extern int tbdm_(real *speech, integer *lpita, integer *tau, integer *ltau, real *amdf, integer *minptr, integer *maxptr, integer *mintau); +extern int voicin_(integer *vwin, real *inbuf, real *lpbuf, integer *buflim, integer *half, real *minamd, real *maxamd, integer *mintau, real *ivrc, integer *obound, integer *voibuf, integer *af, struct lpc10_encoder_state *st); +extern int vparms_(integer *vwin, real *inbuf, real *lpbuf, integer *buflim, integer *half, real *dither, integer *mintau, integer *zc, integer *lbe, integer *fbe, real *qs, real *rc1, real *ar_b__, real *ar_f__); + +#endif + + +#endif /* ! defined F2C_INCLUDE */ diff --git a/libs/codec/lpc10/f2clib.c b/libs/codec/lpc10/f2clib.c new file mode 100644 index 0000000000..aaee644101 --- /dev/null +++ b/libs/codec/lpc10/f2clib.c @@ -0,0 +1,85 @@ +/* + +$Log$ +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:10 jaf + * Initial revision + * + +*/ + +/* + * f2clib.c + * + * SCCS ID: @(#)f2clib.c 1.2 96/05/19 + */ + +#include "f2c.h" + +#ifdef KR_headers +integer pow_ii(ap, bp) integer *ap, *bp; +#else +integer pow_ii(integer *ap, integer *bp) +#endif +{ + integer pow, x, n; + unsigned long u; + + x = *ap; + n = *bp; + + if (n <= 0) { + if (n == 0 || x == 1) + return 1; + if (x != -1) + return x == 0 ? 1/x : 0; + n = -n; + } + u = n; + for(pow = 1; ; ) + { + if(u & 01) + pow *= x; + if(u >>= 1) + x *= x; + else + break; + } + return(pow); + } + + + +#ifdef KR_headers +double r_sign(a,b) real *a, *b; +#else +double r_sign(real *a, real *b) +#endif +{ +double x; +x = (*a >= 0 ? *a : - *a); +return( *b >= 0 ? x : -x); +} + + + +#ifdef KR_headers +double floor(); +integer i_nint(x) real *x; +#else +#undef abs +#include "math.h" +integer i_nint(real *x) +#endif +{ +return( (*x)>=0 ? + floor(*x + .5) : -floor(.5 - *x) ); +} diff --git a/libs/codec/lpc10/ham84.c b/libs/codec/lpc10/ham84.c new file mode 100644 index 0000000000..d6a1351c5c --- /dev/null +++ b/libs/codec/lpc10/ham84.c @@ -0,0 +1,126 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:07 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int ham84_(integer *input, integer *output, integer *errcnt); +#endif + +/* ***************************************************************** */ + +/* HAM84 Version 45G */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:32:07 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/21 15:26:00 jaf */ +/* Put comment header in standard form. */ + +/* Revision 1.2 1996/03/13 22:00:13 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:47:04 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Hamming 8,4 Decoder - can correct 1 out of seven bits */ +/* and can detect up to two errors. */ + +/* Input: */ +/* INPUT - Seven bit data word, 4 bits parameter and */ +/* 4 bits parity information */ +/* Input/Output: */ +/* ERRCNT - Sums errors detected by Hamming code */ +/* Output: */ +/* OUTPUT - 4 corrected parameter bits */ + +/* This subroutine is entered with an eight bit word in INPUT. The 8th */ +/* bit is parity and is stripped off. The remaining 7 bits address the */ +/* hamming 8,4 table and the output OUTPUT from the table gives the 4 */ +/* bits of corrected data. If bit 4 is set, no error was detected. */ +/* ERRCNT is the number of errors counted. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int ham84_(integer *input, integer *output, integer *errcnt) +{ + /* Initialized data */ + + static integer dactab[128] = { 16,0,0,3,0,5,14,7,0,9,14,11,14,13,30,14,0, + 9,2,7,4,7,7,23,9,25,10,9,12,9,14,7,0,5,2,11,5,21,6,5,8,11,11,27, + 12,5,14,11,2,1,18,2,12,5,2,7,12,9,2,11,28,12,12,15,0,3,3,19,4,13, + 6,3,8,13,10,3,13,29,14,13,4,1,10,3,20,4,4,7,10,9,26,10,4,13,10,15, + 8,1,6,3,6,5,22,6,24,8,8,11,8,13,6,15,1,17,2,1,4,1,6,15,8,1,10,15, + 12,15,15,31 }; + + integer i__, j, parity; + +/* Arguments */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Determine parity of input word */ + parity = *input & 255; + parity ^= parity / 16; + parity ^= parity / 4; + parity ^= parity / 2; + parity &= 1; + i__ = dactab[*input & 127]; + *output = i__ & 15; + j = i__ & 16; + if (j != 0) { +/* No errors detected in seven bits */ + if (parity != 0) { + ++(*errcnt); + } + } else { +/* One or two errors detected */ + ++(*errcnt); + if (parity == 0) { +/* Two errors detected */ + ++(*errcnt); + *output = -1; + } + } + return 0; +} /* ham84_ */ + diff --git a/libs/codec/lpc10/hp100.c b/libs/codec/lpc10/hp100.c new file mode 100644 index 0000000000..7c2798e26f --- /dev/null +++ b/libs/codec/lpc10/hp100.c @@ -0,0 +1,169 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:28:05 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:04 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int hp100_(real *speech, integer *start, integer *end, + struct lpc10_encoder_state *st); +extern int inithp100_(void); +#endif + +/* ********************************************************************* */ + +/* HP100 Version 55 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:28:05 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:32:04 jaf + * Initial revision + * */ +/* Revision 1.6 1996/03/15 16:45:25 jaf */ +/* Rearranged a few comments. */ + +/* Revision 1.5 1996/03/14 23:20:54 jaf */ +/* Added comments about when INITHP100 should be used. */ + +/* Revision 1.4 1996/03/14 23:08:08 jaf */ +/* Added an entry named INITHP100 that initializes the local state of */ +/* subroutine HP100. */ + +/* Revision 1.3 1996/03/14 22:09:20 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* Revision 1.2 1996/02/12 15:05:54 jaf */ +/* Added lots of comments explaining why I changed one line, which was a */ +/* declaration with initializations. */ + +/* Revision 1.1 1996/02/07 14:47:12 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* 100 Hz High Pass Filter */ + +/* Jan 92 - corrected typo (1.937148 to 1.935715), */ +/* rounded coefficients to 7 places, */ +/* corrected and merged gain (.97466**4), */ +/* merged numerator into first two sections. */ + +/* Input: */ +/* start, end - Range of samples to filter */ +/* Input/Output: */ +/* speech(end) - Speech data. */ +/* Indices start through end are read and modified. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITHP100. */ +/* Subroutine */ int hp100_(real *speech, integer *start, integer *end, + struct lpc10_encoder_state *st) +{ + /* Temporary local copies of variables in lpc10_encoder_state. + I've only created these because it might cause the loop below + to execute a bit faster to access local variables, rather than + variables in the lpc10_encoder_state structure. It is just a + guess that it will be faster. */ + + real z11; + real z21; + real z12; + real z22; + + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer i__; + real si, err; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Local state */ + /* Parameter adjustments */ + if (speech) { + --speech; + } + + /* Function Body */ + + z11 = st->z11; + z21 = st->z21; + z12 = st->z12; + z22 = st->z22; + + i__1 = *end; + for (i__ = *start; i__ <= i__1; ++i__) { + si = speech[i__]; + err = si + z11 * 1.859076f - z21 * .8648249f; + si = err - z11 * 2.f + z21; + z21 = z11; + z11 = err; + err = si + z12 * 1.935715f - z22 * .9417004f; + si = err - z12 * 2.f + z22; + z22 = z12; + z12 = err; + speech[i__] = si * .902428f; + } + + st->z11 = z11; + st->z21 = z21; + st->z12 = z12; + st->z22 = z22; + + return 0; +} /* hp100_ */ diff --git a/libs/codec/lpc10/invert.c b/libs/codec/lpc10/invert.c new file mode 100644 index 0000000000..8891d1ce86 --- /dev/null +++ b/libs/codec/lpc10/invert.c @@ -0,0 +1,193 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:32:00 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int invert_(integer *order, real *phi, real *psi, real *rc); +#endif + +/* **************************************************************** */ + +/* INVERT Version 45G */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:32:00 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/18 20:52:47 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:51:32 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Eliminated a comment from the original, describing a local array X */ +/* that appeared nowhere in the code. */ + +/* Revision 1.1 1996/02/07 14:47:20 jaf */ +/* Initial revision */ + + +/* **************************************************************** */ + +/* Invert a covariance matrix using Choleski decomposition method. */ + +/* Input: */ +/* ORDER - Analysis order */ +/* PHI(ORDER,ORDER) - Covariance matrix */ +/* Indices (I,J) read, where ORDER .GE. I .GE. J .GE. 1.*/ +/* All other indices untouched. */ +/* PSI(ORDER) - Column vector to be predicted */ +/* Indices 1 through ORDER read. */ +/* Output: */ +/* RC(ORDER) - Pseudo reflection coefficients */ +/* Indices 1 through ORDER written, and then possibly read. +*/ +/* Internal: */ +/* V(ORDER,ORDER) - Temporary matrix */ +/* Same indices written as read from PHI. */ +/* Many indices may be read and written again after */ +/* initially being copied from PHI, but all indices */ +/* are written before being read. */ + +/* NOTE: Temporary matrix V is not needed and may be replaced */ +/* by PHI if the original PHI values do not need to be preserved. */ + +/* Subroutine */ int invert_(integer *order, real *phi, real *psi, real *rc) +{ + /* System generated locals */ + integer phi_dim1, phi_offset, i__1, i__2, i__3; + real r__1, r__2; + + /* Local variables */ + real save; + integer i__, j, k; + real v[100] /* was [10][10] */; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:32:00 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Decompose PHI into V * D * V' where V is a triangular matrix whose */ +/* main diagonal elements are all 1, V' is the transpose of V, and */ +/* D is a vector. Here D(n) is stored in location V(n,n). */ + /* Parameter adjustments */ + --rc; + --psi; + phi_dim1 = *order; + phi_offset = phi_dim1 + 1; + phi -= phi_offset; + + /* Function Body */ + i__1 = *order; + for (j = 1; j <= i__1; ++j) { + i__2 = *order; + for (i__ = j; i__ <= i__2; ++i__) { + v[i__ + j * 10 - 11] = phi[i__ + j * phi_dim1]; + } + i__2 = j - 1; + for (k = 1; k <= i__2; ++k) { + save = v[j + k * 10 - 11] * v[k + k * 10 - 11]; + i__3 = *order; + for (i__ = j; i__ <= i__3; ++i__) { + v[i__ + j * 10 - 11] -= v[i__ + k * 10 - 11] * save; + } + } +/* Compute intermediate results, which are similar to RC's */ + if ((r__1 = v[j + j * 10 - 11], abs(r__1)) < 1e-10f) { + goto L100; + } + rc[j] = psi[j]; + i__2 = j - 1; + for (k = 1; k <= i__2; ++k) { + rc[j] -= rc[k] * v[j + k * 10 - 11]; + } + v[j + j * 10 - 11] = 1.f / v[j + j * 10 - 11]; + rc[j] *= v[j + j * 10 - 11]; +/* Computing MAX */ +/* Computing MIN */ + r__2 = rc[j]; + r__1 = min(r__2,.999f); + rc[j] = max(r__1,-.999f); + } + return 0; +/* Zero out higher order RC's if algorithm terminated early */ +L100: + i__1 = *order; + for (i__ = j; i__ <= i__1; ++i__) { + rc[i__] = 0.f; + } +/* Back substitute for PC's (if needed) */ +/* 110 DO J = ORDER,1,-1 */ +/* PC(J) = RC(J) */ +/* DO I = 1,J-1 */ +/* PC(J) = PC(J) - PC(I)*V(J,I) */ +/* END DO */ +/* END DO */ + return 0; +} /* invert_ */ + diff --git a/libs/codec/lpc10/irc2pc.c b/libs/codec/lpc10/irc2pc.c new file mode 100644 index 0000000000..2a62881868 --- /dev/null +++ b/libs/codec/lpc10/irc2pc.c @@ -0,0 +1,151 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:56 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int irc2pc_(real *rc, real *pc, integer *order, real *gprime, real *g2pass); +#endif + +/* ***************************************************************** */ + +/* IRC2PC Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:31:56 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/20 15:47:19 jaf */ +/* Added comments about which indices of array arguments are read or */ +/* written. */ + +/* Revision 1.2 1996/03/14 16:59:04 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:47:27 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Convert Reflection Coefficients to Predictor Coeficients */ + +/* Inputs: */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER read. */ +/* ORDER - Number of RC's */ +/* GPRIME - Excitation modification gain */ +/* Outputs: */ +/* PC - Predictor coefficients */ +/* Indices 1 through ORDER written. */ +/* Indices 1 through ORDER-1 are read after being written. */ +/* G2PASS - Excitation modification sharpening factor */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int irc2pc_(real *rc, real *pc, integer *order, real *gprime, + real *g2pass) +{ + /* System generated locals */ + integer i__1, i__2; + + /* Builtin functions */ + double sqrt(doublereal); + + /* Local variables */ + real temp[10]; + integer i__, j; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:31:56 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --pc; + --rc; + + /* Function Body */ + *g2pass = 1.f; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + *g2pass *= 1.f - rc[i__] * rc[i__]; + } + *g2pass = *gprime * sqrt(*g2pass); + pc[1] = rc[1]; + i__1 = *order; + for (i__ = 2; i__ <= i__1; ++i__) { + i__2 = i__ - 1; + for (j = 1; j <= i__2; ++j) { + temp[j - 1] = pc[j] - rc[i__] * pc[i__ - j]; + } + i__2 = i__ - 1; + for (j = 1; j <= i__2; ++j) { + pc[j] = temp[j - 1]; + } + pc[i__] = rc[i__]; + } + return 0; +} /* irc2pc_ */ + diff --git a/libs/codec/lpc10/ivfilt.c b/libs/codec/lpc10/ivfilt.c new file mode 100644 index 0000000000..625dd3e327 --- /dev/null +++ b/libs/codec/lpc10/ivfilt.c @@ -0,0 +1,136 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.2 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:53 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int ivfilt_(real *lpbuf, real *ivbuf, integer *len, integer *nsamp, real *ivrc); +#endif + +/* ********************************************************************* */ + +/* IVFILT Version 48 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.2 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:31:53 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/15 21:36:29 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 00:01:00 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:47:34 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* 2nd order inverse filter, speech is decimated 4:1 */ + +/* Input: */ +/* LEN - Length of speech buffers */ +/* NSAMP - Number of samples to filter */ +/* LPBUF - Low pass filtered speech buffer */ +/* Indices LEN-NSAMP-7 through LEN read. */ +/* Output: */ +/* IVBUF - Inverse filtered speech buffer */ +/* Indices LEN-NSAMP+1 through LEN written. */ +/* IVRC - Inverse filter reflection coefficients (for voicing) */ +/* Indices 1 and 2 both written (also read, but only after writing). +*/ + +/* This subroutine has no local state. */ + +/* Subroutine */ int ivfilt_(real *lpbuf, real *ivbuf, integer *len, integer * + nsamp, real *ivrc) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer i__, j, k; + real r__[3], pc1, pc2; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Local state */ +/* None */ +/* Calculate Autocorrelations */ + /* Parameter adjustments */ + --ivbuf; + --lpbuf; + --ivrc; + + /* Function Body */ + for (i__ = 1; i__ <= 3; ++i__) { + r__[i__ - 1] = 0.f; + k = (i__ - 1) << 2; + i__1 = *len; + for (j = (i__ << 2) + *len - *nsamp; j <= i__1; j += 2) { + r__[i__ - 1] += lpbuf[j] * lpbuf[j - k]; + } + } +/* Calculate predictor coefficients */ + pc1 = 0.f; + pc2 = 0.f; + ivrc[1] = 0.f; + ivrc[2] = 0.f; + if (r__[0] > 1e-10f) { + ivrc[1] = r__[1] / r__[0]; + ivrc[2] = (r__[2] - ivrc[1] * r__[1]) / (r__[0] - ivrc[1] * r__[1]); + pc1 = ivrc[1] - ivrc[1] * ivrc[2]; + pc2 = ivrc[2]; + } +/* Inverse filter LPBUF into IVBUF */ + i__1 = *len; + for (i__ = *len + 1 - *nsamp; i__ <= i__1; ++i__) { + ivbuf[i__] = lpbuf[i__] - pc1 * lpbuf[i__ - 4] - pc2 * lpbuf[i__ - 8]; + } + return 0; +} /* ivfilt_ */ + diff --git a/libs/codec/lpc10/lpc10.h b/libs/codec/lpc10/lpc10.h new file mode 100644 index 0000000000..17d04910b7 --- /dev/null +++ b/libs/codec/lpc10/lpc10.h @@ -0,0 +1,248 @@ +/* + +$Log$ +Revision 1.18 2004/08/31 13:32:11 markster +Merge NetBSD and Courtesty tone with modifications (bug #2329) + +Revision 1.17 2003/10/26 18:50:49 markster +Make it build and run on MacOS X + +Revision 1.3 2003/10/26 18:50:49 markster +Make it build and run on MacOS X + +Revision 1.2 2003/04/23 19:13:35 markster +More OpenBSD patches + +Revision 1.1.1.2 2003/03/16 22:37:30 matteo +dom mar 16 23:37:23 CET 2003 + +Revision 1.2 2003/03/16 16:09:48 markster +Mere James's cleanups for fewer build warnings + +Revision 1.1 2000/01/05 00:20:06 markster +Add broken lpc10 code... It's not too far from working I don't think... + + * Revision 1.1 1996/08/19 22:47:31 jaf + * Initial revision + * + +*/ + +#ifndef __LPC10_H__ +#define __LPC10_H__ + +#define LPC10_SAMPLES_PER_FRAME 180 +#define LPC10_BITS_IN_COMPRESSED_FRAME 54 + + +/* + + The "#if defined"'s in this file are by no means intended to be + complete. They are what Nautilus uses, which has been successfully + compiled under DOS with the Microsoft C compiler, and under a few + versions of Unix with the GNU C compiler. + + */ + +#if defined(unix) || defined(__unix__) || defined(__NetBSD__) +typedef short INT16; +typedef int INT32; +#endif + + +#if defined(__MSDOS__) || defined(MSDOS) +typedef int INT16; +typedef long INT32; +#endif + +#if defined(__APPLE__) +typedef short INT16; +typedef int INT32; +#endif + + +/* The initial values for every member of this structure is 0, except + where noted in comments. */ + +/* These two lines are copied from f2c.h. There should be a more + elegant way of doing this than having the same declarations in two + files. */ + +typedef float real; +typedef INT32 integer; +typedef INT32 logical; +typedef INT16 shortint; + +struct lpc10_encoder_state { + /* State used only by function hp100 */ + real z11; + real z21; + real z12; + real z22; + + /* State used by function analys */ + real inbuf[540], pebuf[540]; + real lpbuf[696], ivbuf[312]; + real bias; + integer osbuf[10]; /* no initial value necessary */ + integer osptr; /* initial value 1 */ + integer obound[3]; + integer vwin[6] /* was [2][3] */; /* initial value vwin[4] = 307; vwin[5] = 462; */ + integer awin[6] /* was [2][3] */; /* initial value awin[4] = 307; awin[5] = 462; */ + integer voibuf[8] /* was [2][4] */; + real rmsbuf[3]; + real rcbuf[30] /* was [10][3] */; + real zpre; + + + /* State used by function onset */ + real n; + real d__; /* initial value 1.f */ + real fpc; /* no initial value necessary */ + real l2buf[16]; + real l2sum1; + integer l2ptr1; /* initial value 1 */ + integer l2ptr2; /* initial value 9 */ + integer lasti; /* no initial value necessary */ + logical hyst; /* initial value FALSE_ */ + + /* State used by function voicin */ + real dither; /* initial value 20.f */ + real snr; + real maxmin; + real voice[6] /* was [2][3] */; /* initial value is probably unnecessary */ + integer lbve, lbue, fbve, fbue; + integer ofbue, sfbue; + integer olbue, slbue; + /* Initial values: + lbve = 3000; + fbve = 3000; + fbue = 187; + ofbue = 187; + sfbue = 187; + lbue = 93; + olbue = 93; + slbue = 93; + snr = (real) (fbve / fbue << 6); + */ + + /* State used by function dyptrk */ + real s[60]; + integer p[120] /* was [60][2] */; + integer ipoint; + real alphax; + + /* State used by function chanwr */ + integer isync; + +}; + + +struct lpc10_decoder_state { + + /* State used by function decode */ + integer iptold; /* initial value 60 */ + logical first; /* initial value TRUE_ */ + integer ivp2h; + integer iovoic; + integer iavgp; /* initial value 60 */ + integer erate; + integer drc[30] /* was [3][10] */; + integer dpit[3]; + integer drms[3]; + + /* State used by function synths */ + real buf[360]; + integer buflen; /* initial value 180 */ + + /* State used by function pitsyn */ + integer ivoico; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + integer ipito; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + real rmso; /* initial value 1.f */ + real rco[10]; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + integer jsamp; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + logical first_pitsyn; /* initial value TRUE_ */ + + /* State used by function bsynz */ + integer ipo; + real exc[166]; + real exc2[166]; + real lpi1; + real lpi2; + real lpi3; + real hpi1; + real hpi2; + real hpi3; + real rmso_bsynz; + + /* State used by function random */ + integer j; /* initial value 2 */ + integer k; /* initial value 5 */ + shortint y[5]; /* initial value { -21161,-8478,30892,-10216,16950 } */ + + /* State used by function deemp */ + real dei1; + real dei2; + real deo1; + real deo2; + real deo3; + +}; + + + +/* + + Calling sequence: + + Call create_lpc10_encoder_state(), which returns a pointer to an + already initialized lpc10_encoder_state structure. + + lpc10_encode reads indices 0 through (LPC10_SAMPLES_PER_FRAME-1) of + array speech[], and writes indices 0 through + (LPC10_BITS_IN_COMPRESSED_FRAME-1) of array bits[], and both reads + and writes the lpc10_encoder_state structure contents. The + lpc10_encoder_state structure should *not* be initialized for every + frame of encoded speech. Once at the beginning of execution, done + automatically for you by create_lpc10_encoder_state(), is enough. + + init_lpc10_encoder_state() reinitializes the lpc10_encoder_state + structure. This might be useful if you are finished processing one + sound sample, and want to reuse the same lpc10_encoder_state + structure to process another sound sample. There might be other + uses as well. + + Note that the comments in the lpc10/lpcenc.c file imply that indices + 1 through 180 of array speech[] are read. These comments were + written for the Fortran version of the code, before it was + automatically converted to C by the conversion program f2c. f2c + seems to use the convention that the pointers to arrays passed as + function arguments point to the first index used in the Fortran + code, whatever index that might be (usually 1), and then it modifies + the pointer inside of the function, like so: + + if (speech) { + --speech; + } + + So that the code can access the first value at index 1 and the last + at index 180. This makes the translated C code "closer" to the + original Fortran code. + + The calling sequence for the decoder is similar to the encoder. The + only significant difference is that the array bits[] is read + (indices 0 through (LPC10_BITS_IN_COMPRESSED_FRAME-1)), and the + array speech[] is written (indices 0 through + (LPC10_SAMPLES_PER_FRAME-1)). + + */ + +struct lpc10_encoder_state * create_lpc10_encoder_state (void); +void init_lpc10_encoder_state (struct lpc10_encoder_state *st); +int lpc10_encode (real *speech, INT32 *bits, struct lpc10_encoder_state *st); + +struct lpc10_decoder_state * create_lpc10_decoder_state (void); +void init_lpc10_decoder_state (struct lpc10_decoder_state *st); +int lpc10_decode (INT32 *bits, real *speech, struct lpc10_decoder_state *st); + +#endif /* __LPC10_H__ */ diff --git a/libs/codec/lpc10/lpcdec.c b/libs/codec/lpc10/lpcdec.c new file mode 100644 index 0000000000..095f6f7d51 --- /dev/null +++ b/libs/codec/lpc10/lpcdec.c @@ -0,0 +1,297 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:30:11 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:48 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int lpcdec_(integer *bits, real *speech); +extern int initlpcdec_(void); +/* comlen contrl_ 12 */ +/*:ref: chanrd_ 14 5 4 4 4 4 4 */ +/*:ref: decode_ 14 7 4 4 4 4 4 6 6 */ +/*:ref: synths_ 14 6 4 4 6 6 6 4 */ +/*:ref: initdecode_ 14 0 */ +/*:ref: initsynths_ 14 0 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static integer c__10 = 10; + +/* ***************************************************************** */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:30:11 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:48 jaf + * Initial revision + * */ +/* Revision 1.1 1996/03/28 00:03:00 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Decode 54 bits to one frame of 180 speech samples. */ + +/* Input: */ +/* BITS - 54 encoded bits, stored 1 per array element. */ +/* Indices 1 through 53 read (SYNC bit ignored). */ +/* Output: */ +/* SPEECH - Speech encoded as real values in the range [-1,+1]. */ +/* Indices 1 through 180 written. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITLPCDEC. */ + +/* Subroutine */ int lpc10_decode(integer *bits, real *speech, + struct lpc10_decoder_state *st) +{ + integer irms, voice[2], pitch, ipitv; + extern /* Subroutine */ int decode_(integer *, integer *, integer *, + integer *, integer *, real *, real *, struct lpc10_decoder_state *); + real rc[10]; + extern /* Subroutine */ int chanrd_(integer *, integer *, integer *, + integer *, integer *), synths_(integer *, + integer *, real *, real *, real *, integer *, + struct lpc10_decoder_state *); + integer irc[10], len; + real rms; + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:30:11 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:48 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:30:11 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:48 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Local variables that need not be saved */ +/* Uncoded speech parameters */ +/* Coded speech parameters */ +/* Others */ +/* Local state */ +/* None */ + /* Parameter adjustments */ + if (bits) { + --bits; + } + if (speech) { + --speech; + } + + /* Function Body */ + + chanrd_(&c__10, &ipitv, &irms, irc, &bits[1]); + decode_(&ipitv, &irms, irc, voice, &pitch, &rms, rc, st); + synths_(voice, &pitch, &rms, rc, &speech[1], &len, st); + return 0; +} /* lpcdec_ */ diff --git a/libs/codec/lpc10/lpcenc.c b/libs/codec/lpc10/lpcenc.c new file mode 100644 index 0000000000..cb90d21cea --- /dev/null +++ b/libs/codec/lpc10/lpcenc.c @@ -0,0 +1,181 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:31:21 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:44 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int lpcenc_(real *speech, integer *bits); +extern int initlpcenc_(void); +/*:ref: prepro_ 14 2 6 4 */ +/*:ref: analys_ 14 5 6 4 4 6 6 */ +/*:ref: encode_ 14 7 4 4 6 6 4 4 4 */ +/*:ref: chanwr_ 14 5 4 4 4 4 4 */ +/*:ref: initprepro_ 14 0 */ +/*:ref: initanalys_ 14 0 */ +#endif + +/* Table of constant values */ + +static integer c__180 = 180; +static integer c__10 = 10; + +/* ***************************************************************** */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:31:21 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:44 jaf + * Initial revision + * */ +/* Revision 1.2 1996/03/28 00:01:22 jaf */ +/* Commented out some trace statements. */ + +/* Revision 1.1 1996/03/28 00:00:27 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Encode one frame of 180 speech samples to 54 bits. */ + +/* Input: */ +/* SPEECH - Speech encoded as real values in the range [-1,+1]. */ +/* Indices 1 through 180 read, and modified (by PREPRO). */ +/* Output: */ +/* BITS - 54 encoded bits, stored 1 per array element. */ +/* Indices 1 through 54 written. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITLPCENC. */ + +/* Subroutine */ int lpc10_encode(real *speech, integer *bits, + struct lpc10_encoder_state *st) +{ + integer irms, voice[2], pitch, ipitv; + real rc[10]; + extern /* Subroutine */ int encode_(integer *, integer *, real *, real *, + integer *, integer *, integer *), chanwr_(integer *, integer *, + integer *, integer *, integer *, struct lpc10_encoder_state *), + analys_(real *, integer *, + integer *, real *, real *, struct lpc10_encoder_state *), + prepro_(real *, integer *, struct lpc10_encoder_state *); + integer irc[10]; + real rms; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:31:21 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Changed name of function from lpcenc_ to lpc10_encode, simply to make + * all lpc10 functions have more consistent naming with each other. + * + * Revision 1.1 1996/08/19 22:31:44 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Local variables that need not be saved */ +/* Uncoded speech parameters */ +/* Coded speech parameters */ +/* Local state */ +/* None */ + /* Parameter adjustments */ + if (speech) { + --speech; + } + if (bits) { + --bits; + } + + /* Function Body */ + prepro_(&speech[1], &c__180, st); + analys_(&speech[1], voice, &pitch, &rms, rc, st); + encode_(voice, &pitch, &rms, rc, &ipitv, &irms, irc); + chanwr_(&c__10, &ipitv, &irms, irc, &bits[1], st); + return 0; +} /* lpcenc_ */ diff --git a/libs/codec/lpc10/lpcini.c b/libs/codec/lpc10/lpcini.c new file mode 100644 index 0000000000..fbaf2f628f --- /dev/null +++ b/libs/codec/lpc10/lpcini.c @@ -0,0 +1,446 @@ +/* + +$Log$ +Revision 1.18 2003/10/21 18:08:11 markster +Fix include order + +Revision 1.5 2003/10/21 18:08:11 markster +Fix include order + +Revision 1.4 2003/10/21 02:57:29 markster +FreeBSD patch, take 2 + +Revision 1.3 2003/10/16 21:11:30 martinp +Revert the previous patch since it's braking compilation + +Revision 1.1 2003/02/12 13:59:15 matteo +Initial revision + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:35:41 jaf + * Added functions for allocating and initializing lpc10_encoder_state + * and lpc10_decoder_state structures. + * + * Revision 1.1 1996/08/19 22:31:40 jaf + * Initial revision + * + +*/ + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int lpcini_(void); +/* comlen contrl_ 12 */ +/*:ref: initlpcenc_ 14 0 */ +/*:ref: initlpcdec_ 14 0 */ +#endif + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include +#include "f2c.h" + +/* Common Block Declarations */ + +struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* ***************************************************************** */ + +/* $Log$ + * Revision 1.18 2003/10/21 18:08:11 markster + * Fix include order + * +/* Revision 1.5 2003/10/21 18:08:11 markster +/* Fix include order +/* +/* Revision 1.4 2003/10/21 02:57:29 markster +/* FreeBSD patch, take 2 +/* +/* Revision 1.3 2003/10/16 21:11:30 martinp +/* Revert the previous patch since it's braking compilation +/* +/* Revision 1.1 2003/02/12 13:59:15 matteo +/* Initial revision +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:35:41 jaf + * Added functions for allocating and initializing lpc10_encoder_state + * and lpc10_decoder_state structures. + * + * Revision 1.1 1996/08/19 22:31:40 jaf + * Initial revision + * */ +/* Revision 1.1 1996/03/28 00:04:05 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Initialize COMMON block variables used by LPC-10 encoder and decoder, */ +/* and call initialization routines for both of them. */ + +/* Subroutine */ int lpcini_(void) +{ + +/* $Log$ + * Revision 1.18 2003/10/21 18:08:11 markster + * Fix include order + * +/* Revision 1.5 2003/10/21 18:08:11 markster +/* Fix include order +/* +/* Revision 1.4 2003/10/21 02:57:29 markster +/* FreeBSD patch, take 2 +/* +/* Revision 1.3 2003/10/16 21:11:30 martinp +/* Revert the previous patch since it's braking compilation +/* +/* Revision 1.1 2003/02/12 13:59:15 matteo +/* Initial revision +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:35:41 jaf + * Added functions for allocating and initializing lpc10_encoder_state + * and lpc10_decoder_state structures. + * + * Revision 1.1 1996/08/19 22:31:40 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* $Log$ + * Revision 1.18 2003/10/21 18:08:11 markster + * Fix include order + * +/* Revision 1.5 2003/10/21 18:08:11 markster +/* Fix include order +/* +/* Revision 1.4 2003/10/21 02:57:29 markster +/* FreeBSD patch, take 2 +/* +/* Revision 1.3 2003/10/16 21:11:30 martinp +/* Revert the previous patch since it's braking compilation +/* +/* Revision 1.1 2003/02/12 13:59:15 matteo +/* Initial revision +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:35:41 jaf + * Added functions for allocating and initializing lpc10_encoder_state + * and lpc10_decoder_state structures. + * + * Revision 1.1 1996/08/19 22:31:40 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ + contrl_1.order = 10; + contrl_1.lframe = 180; + contrl_1.corrp = TRUE_; + return 0; +} /* lpcini_ */ + + + +/* Allocate memory for, and initialize, the state that needs to be + kept from encoding one frame to the next for a single + LPC-10-compressed audio stream. Return 0 if malloc fails, + otherwise return pointer to new structure. */ + +struct lpc10_encoder_state * +create_lpc10_encoder_state() +{ + struct lpc10_encoder_state *st; + + st = (struct lpc10_encoder_state *) + malloc((unsigned) sizeof (struct lpc10_encoder_state)); + if (st != 0) { + init_lpc10_encoder_state(st); + } + return (st); +} + + + +void init_lpc10_encoder_state(struct lpc10_encoder_state *st) +{ + int i; + + lpcini_(); + + /* State used only by function hp100 */ + st->z11 = 0.0f; + st->z21 = 0.0f; + st->z12 = 0.0f; + st->z22 = 0.0f; + + /* State used by function analys */ + for (i = 0; i < 540; i++) { + st->inbuf[i] = 0.0f; + st->pebuf[i] = 0.0f; + } + for (i = 0; i < 696; i++) { + st->lpbuf[i] = 0.0f; + } + for (i = 0; i < 312; i++) { + st->ivbuf[i] = 0.0f; + } + st->bias = 0.0f; + /* integer osbuf[10]; /* no initial value necessary */ + st->osptr = 1; + for (i = 0; i < 3; i++) { + st->obound[i] = 0; + } + st->vwin[4] = 307; + st->vwin[5] = 462; + st->awin[4] = 307; + st->awin[5] = 462; + for (i = 0; i < 8; i++) { + st->voibuf[i] = 0; + } + for (i = 0; i < 3; i++) { + st->rmsbuf[i] = 0.0f; + } + for (i = 0; i < 30; i++) { + st->rcbuf[i] = 0.0f; + } + st->zpre = 0.0f; + + + /* State used by function onset */ + st->n = 0.0f; + st->d__ = 1.0f; + /* real fpc; /* no initial value necessary */ + for (i = 0; i < 16; i++) { + st->l2buf[i] = 0.0f; + } + st->l2sum1 = 0.0f; + st->l2ptr1 = 1; + st->l2ptr2 = 9; + /* integer lasti; /* no initial value necessary */ + st->hyst = FALSE_; + + /* State used by function voicin */ + st->dither = 20.0f; + st->maxmin = 0.0f; + for (i = 0; i < 6; i++) { + st->voice[i] = 0.0f; + } + st->lbve = 3000; + st->fbve = 3000; + st->fbue = 187; + st->ofbue = 187; + st->sfbue = 187; + st->lbue = 93; + st->olbue = 93; + st->slbue = 93; + st->snr = (real) (st->fbve / st->fbue << 6); + + /* State used by function dyptrk */ + for (i = 0; i < 60; i++) { + st->s[i] = 0.0f; + } + for (i = 0; i < 120; i++) { + st->p[i] = 0; + } + st->ipoint = 0; + st->alphax = 0.0f; + + /* State used by function chanwr */ + st->isync = 0; + +} + + + +/* Allocate memory for, and initialize, the state that needs to be + kept from decoding one frame to the next for a single + LPC-10-compressed audio stream. Return 0 if malloc fails, + otherwise return pointer to new structure. */ + +struct lpc10_decoder_state * +create_lpc10_decoder_state() +{ + struct lpc10_decoder_state *st; + + st = (struct lpc10_decoder_state *) + malloc((unsigned) sizeof (struct lpc10_decoder_state)); + if (st != 0) { + init_lpc10_decoder_state(st); + } + return (st); +} + + + +void init_lpc10_decoder_state(struct lpc10_decoder_state *st) +{ + int i; + + lpcini_(); + + /* State used by function decode */ + st->iptold = 60; + st->first = TRUE_; + st->ivp2h = 0; + st->iovoic = 0; + st->iavgp = 60; + st->erate = 0; + for (i = 0; i < 30; i++) { + st->drc[i] = 0; + } + for (i = 0; i < 3; i++) { + st->dpit[i] = 0; + st->drms[i] = 0; + } + + /* State used by function synths */ + for (i = 0; i < 360; i++) { + st->buf[i] = 0.0f; + } + st->buflen = 180; + + /* State used by function pitsyn */ + /* ivoico; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + /* ipito; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + st->rmso = 1.0f; + /* rco[10]; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + /* integer jsamp; /* no initial value necessary as long as first_pitsyn is initially TRUE_ */ + st->first_pitsyn = TRUE_; + + /* State used by function bsynz */ + st->ipo = 0; + for (i = 0; i < 166; i++) { + st->exc[i] = 0.0f; + st->exc2[i] = 0.0f; + } + st->lpi1 = 0.0f; + st->lpi2 = 0.0f; + st->lpi3 = 0.0f; + st->hpi1 = 0.0f; + st->hpi2 = 0.0f; + st->hpi3 = 0.0f; + st->rmso_bsynz = 0.0f; + + /* State used by function random */ + st->j = 2; + st->k = 5; + st->y[0] = (shortint) -21161; + st->y[1] = (shortint) -8478; + st->y[2] = (shortint) 30892; + st->y[3] = (shortint) -10216; + st->y[4] = (shortint) 16950; + + /* State used by function deemp */ + st->dei1 = 0.0f; + st->dei2 = 0.0f; + st->deo1 = 0.0f; + st->deo2 = 0.0f; + st->deo3 = 0.0f; +} diff --git a/libs/codec/lpc10/lpfilt.c b/libs/codec/lpc10/lpfilt.c new file mode 100644 index 0000000000..35ff5a408e --- /dev/null +++ b/libs/codec/lpc10/lpfilt.c @@ -0,0 +1,125 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:35 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int lpfilt_(real *inbuf, real *lpbuf, integer *len, integer *nsamp); +#endif + +/* *********************************************************************** */ + +/* LPFILT Version 55 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:31:35 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/15 16:53:49 jaf */ +/* Just put comment header in standard form. */ + +/* Revision 1.2 1996/03/12 23:58:06 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:47:44 jaf */ +/* Initial revision */ + + +/* *********************************************************************** */ + +/* 31 Point Equiripple FIR Low-Pass Filter */ +/* Linear phase, delay = 15 samples */ + +/* Passband: ripple = 0.25 dB, cutoff = 800 Hz */ +/* Stopband: atten. = 40. dB, cutoff = 1240 Hz */ + +/* Inputs: */ +/* LEN - Length of speech buffers */ +/* NSAMP - Number of samples to filter */ +/* INBUF - Input speech buffer */ +/* Indices len-nsamp-29 through len are read. */ +/* Output: */ +/* LPBUF - Low passed speech buffer (must be different array than INBUF) */ +/* Indices len+1-nsamp through len are written. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int lpfilt_(real *inbuf, real *lpbuf, integer *len, integer * + nsamp) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + integer j; + real t; + +/* Arguments */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Local state */ +/* None */ + /* Parameter adjustments */ + --lpbuf; + --inbuf; + + /* Function Body */ + i__1 = *len; + for (j = *len + 1 - *nsamp; j <= i__1; ++j) { + t = (inbuf[j] + inbuf[j - 30]) * -.0097201988f; + t += (inbuf[j - 1] + inbuf[j - 29]) * -.0105179986f; + t += (inbuf[j - 2] + inbuf[j - 28]) * -.0083479648f; + t += (inbuf[j - 3] + inbuf[j - 27]) * 5.860774e-4f; + t += (inbuf[j - 4] + inbuf[j - 26]) * .0130892089f; + t += (inbuf[j - 5] + inbuf[j - 25]) * .0217052232f; + t += (inbuf[j - 6] + inbuf[j - 24]) * .0184161253f; + t += (inbuf[j - 7] + inbuf[j - 23]) * 3.39723e-4f; + t += (inbuf[j - 8] + inbuf[j - 22]) * -.0260797087f; + t += (inbuf[j - 9] + inbuf[j - 21]) * -.0455563702f; + t += (inbuf[j - 10] + inbuf[j - 20]) * -.040306855f; + t += (inbuf[j - 11] + inbuf[j - 19]) * 5.029835e-4f; + t += (inbuf[j - 12] + inbuf[j - 18]) * .0729262903f; + t += (inbuf[j - 13] + inbuf[j - 17]) * .1572008878f; + t += (inbuf[j - 14] + inbuf[j - 16]) * .2247288674f; + t += inbuf[j - 15] * .250535965f; + lpbuf[j] = t; + } + return 0; +} /* lpfilt_ */ + diff --git a/libs/codec/lpc10/median.c b/libs/codec/lpc10/median.c new file mode 100644 index 0000000000..a40dd1e813 --- /dev/null +++ b/libs/codec/lpc10/median.c @@ -0,0 +1,89 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:31 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern integer median_(integer *d1, integer *d2, integer *d3); +#endif + +/* ********************************************************************* */ + +/* MEDIAN Version 45G */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:31:31 jaf + * Initial revision + * */ +/* Revision 1.2 1996/03/14 22:30:22 jaf */ +/* Just rearranged the comments and local variable declarations a bit. */ + +/* Revision 1.1 1996/02/07 14:47:53 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Find median of three values */ + +/* Input: */ +/* D1,D2,D3 - Three input values */ +/* Output: */ +/* MEDIAN - Median value */ + +integer median_(integer *d1, integer *d2, integer *d3) +{ + /* System generated locals */ + integer ret_val; + +/* Arguments */ + ret_val = *d2; + if (*d2 > *d1 && *d2 > *d3) { + ret_val = *d1; + if (*d3 > *d1) { + ret_val = *d3; + } + } else if (*d2 < *d1 && *d2 < *d3) { + ret_val = *d1; + if (*d3 < *d1) { + ret_val = *d3; + } + } + return ret_val; +} /* median_ */ + diff --git a/libs/codec/lpc10/mload.c b/libs/codec/lpc10/mload.c new file mode 100644 index 0000000000..084737420d --- /dev/null +++ b/libs/codec/lpc10/mload.c @@ -0,0 +1,163 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:25 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int mload_(integer *order, integer *awins, integer *awinf, real *speech, real *phi, real *psi); +#endif + +/* ***************************************************************** */ + +/* MLOAD Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:31:25 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/27 23:59:51 jaf */ +/* Added some more accurate comments about which indices of the argument */ +/* array SPEECH are read. I thought that this might be the cause of a */ +/* problem I've been having, but it isn't. */ + +/* Revision 1.4 1996/03/26 19:16:53 jaf */ +/* Commented out the code at the end that copied the lower triangular */ +/* half of PHI into the upper triangular half (making the resulting */ +/* matrix symmetric). The upper triangular half was never used by later */ +/* code in subroutine ANALYS. */ + +/* Revision 1.3 1996/03/18 21:16:00 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:47:41 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:48:01 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Load a covariance matrix. */ + +/* Input: */ +/* ORDER - Analysis order */ +/* AWINS - Analysis window start */ +/* AWINF - Analysis window finish */ +/* SPEECH(AWINF) - Speech buffer */ +/* Indices MIN(AWINS, AWINF-(ORDER-1)) through */ +/* MAX(AWINF, AWINS+(ORDER-1)) read. */ +/* As long as (AWINF-AWINS) .GE. (ORDER-1), */ +/* this is just indices AWINS through AWINF. */ +/* Output: */ +/* PHI(ORDER,ORDER) - Covariance matrix */ +/* Lower triangular half and diagonal written, and read.*/ +/* Upper triangular half untouched. */ +/* PSI(ORDER) - Prediction vector */ +/* Indices 1 through ORDER written, */ +/* and most are read after that. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int mload_(integer *order, integer *awins, integer *awinf, + real *speech, real *phi, real *psi) +{ + /* System generated locals */ + integer phi_dim1, phi_offset, i__1, i__2; + + /* Local variables */ + integer c__, i__, r__, start; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Load first column of triangular covariance matrix PHI */ + /* Parameter adjustments */ + --psi; + phi_dim1 = *order; + phi_offset = phi_dim1 + 1; + phi -= phi_offset; + --speech; + + /* Function Body */ + start = *awins + *order; + i__1 = *order; + for (r__ = 1; r__ <= i__1; ++r__) { + phi[r__ + phi_dim1] = 0.f; + i__2 = *awinf; + for (i__ = start; i__ <= i__2; ++i__) { + phi[r__ + phi_dim1] += speech[i__ - 1] * speech[i__ - r__]; + } + } +/* Load last element of vector PSI */ + psi[*order] = 0.f; + i__1 = *awinf; + for (i__ = start; i__ <= i__1; ++i__) { + psi[*order] += speech[i__] * speech[i__ - *order]; + } +/* End correct to get additional columns of PHI */ + i__1 = *order; + for (r__ = 2; r__ <= i__1; ++r__) { + i__2 = r__; + for (c__ = 2; c__ <= i__2; ++c__) { + phi[r__ + c__ * phi_dim1] = phi[r__ - 1 + (c__ - 1) * phi_dim1] - + speech[*awinf + 1 - r__] * speech[*awinf + 1 - c__] + + speech[start - r__] * speech[start - c__]; + } + } +/* End correct to get additional elements of PSI */ + i__1 = *order - 1; + for (c__ = 1; c__ <= i__1; ++c__) { + psi[c__] = phi[c__ + 1 + phi_dim1] - speech[start - 1] * speech[start + - 1 - c__] + speech[*awinf] * speech[*awinf - c__]; + } +/* Copy lower triangular section into upper (why bother?) */ +/* I'm commenting this out, since the upper triangular half of PHI +*/ +/* is never used by later code, unless a sufficiently high level of +*/ +/* tracing is turned on. */ +/* DO R = 1,ORDER */ +/* DO C = 1,R-1 */ +/* PHI(C,R) = PHI(R,C) */ +/* END DO */ +/* END DO */ + return 0; +} /* mload_ */ + diff --git a/libs/codec/lpc10/onset.c b/libs/codec/lpc10/onset.c new file mode 100644 index 0000000000..1d682c1c16 --- /dev/null +++ b/libs/codec/lpc10/onset.c @@ -0,0 +1,324 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:37:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:31:18 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int onset_(real *pebuf, integer *osbuf, integer *osptr, integer *oslen, integer *sbufl, integer *sbufh, integer *lframe, struct lpc10_encoder_state *st); +#endif + +/* Table of constant values */ + +static real c_b2 = 1.f; + +/* ****************************************************************** */ + +/* ONSET Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:37:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:31:18 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/15 16:41:01 jaf */ +/* Just rearranged INITONSET assignment orders to be consistent with */ +/* order of DATA statements in ONSET. */ + +/* Revision 1.4 1996/03/15 15:48:27 jaf */ +/* Changed some comments, and only reordered the DATA statements (their */ +/* meaning wasn't changed). */ + +/* Revision 1.3 1996/03/14 23:53:06 jaf */ +/* Added an entry INITONSET that reinitializes the local state variables */ +/* of subroutine ONSET. */ + +/* Rearranged quite a few comments, adding more explaining which */ +/* arguments were inputs, and how the modified ones can be changed. */ + +/* Revision 1.2 1996/03/12 23:53:00 jaf */ +/* Lots of comments added about the local state of this subroutine that */ +/* must be saved from one invocation to the next. */ + +/* One constant 180 replaced with LFRAME, which should be "more general", */ +/* even though it would probably require many more changes than this to */ +/* get this coder to work for other frame sizes. */ + +/* Revision 1.1 1996/02/07 14:48:09 jaf */ +/* Initial revision */ + + +/* ****************************************************************** */ + +/* Floating point version */ + + +/* Detection of onsets in (or slightly preceding) the futuremost frame */ +/* of speech. */ + + +/* Input: */ +/* PEBUF(SBUFL:SBUFH) - Preemphasized speech */ +/* Indices SBUFH-LFRAME through SBUFH are read. */ +/* OSLEN - Maximum number of onsets that can be stored in OSBUF. */ +/* SBUFL, SBUFH - Range of PEBUF */ +/* LFRAME - length of a frame, in samples */ +/* Input/Output: */ +/* OSBUF(OSLEN) - Buffer which holds sorted indexes of onsets */ +/* Indices A through B are modified, where A */ +/* is the original value of OSPTR, and B is the final */ +/* value of OSPTR-1. B is at most OSLEN. */ +/* OSPTR - Free pointer into OSBUF */ +/* Initial value should be .LE. OSLEN+1. */ +/* If so, final value grows by one for each new onset */ +/* found, and final value will be .LE. OSLEN+1. */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this subroutine, or */ +/* reinitialize its state for any other reason, call the ENTRY INITONSET. */ + +/* Subroutine */ int onset_(real *pebuf, integer *osbuf, integer * + osptr, integer *oslen, integer *sbufl, integer *sbufh, integer * + lframe, struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + real *n; + real *d__; + real *l2buf; + real *l2sum1; + integer *l2ptr1; + integer *l2ptr2; + logical *hyst; + + /* System generated locals */ + integer pebuf_offset, i__1; + real r__1; + + /* Builtin functions */ + double r_sign(real *, real *); + + /* Local variables */ + integer i__; + integer *lasti; + real l2sum2; + real *fpc; + +/* Arguments */ +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:37:55 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:31:18 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Parameters/constants */ +/* Parameters for onset detection algorithm: */ +/* L2 Threshold for filtered slope of FPC (function of L2WID!) */ +/* L2LAG Lag due to both filters which compute filtered slope of FPC */ +/* L2WID Width of the filter which computes the slope of FPC */ +/* OSHYST The number of samples of slope(FPC) which must be below */ +/* the threshold before a new onset may be declared. */ +/* Local variables that need not be saved */ +/* Local state */ +/* Variables */ +/* N, D Numerator and denominator of prediction filters */ +/* FPC Current prediction coefs */ +/* L2BUF, L2SUM1, L2SUM2 State of slope filter */ +/* The only "significant" change I've made is to change L2SUM2 out +*/ +/* of the list of local variables that need to be saved, since it */ +/* didn't need to be. */ +/* L2SUM1 need not be, but avoiding saving it would require a small +*/ +/* change to the body of the code. See comments below for an */ +/* example of how the code could be changed to avoid saving L2SUM1. +*/ +/* FPC and LASTI are saved from one invocation to the next, but */ +/* they are not given initial values. This is acceptable, because +*/ +/* FPC will be assigned a value the first time that this function */ +/* is called after D is initialized to 1, since the formula to */ +/* change D will not change it to 0 in one step, and the IF (D */ +/* .NE. 0) statement will execute its THEN part, initializing FPC. +*/ + +/* LASTI's value will not be used until HYST is .TRUE., and */ +/* whenever HYST is changed from its initial value of .FALSE., */ +/* LASTI is assigned a value. */ +/* In a C version of this coder, it would be nice if all of these */ +/* saved things, in this and all other subroutines, could be stored +*/ +/* in a single struct lpc10_coder_state_t, initialized with a call +*/ +/* to a function like lpc10_init(&lpc10_coder_state). In this way, +*/ +/* a program that used these functions could conveniently alternate +*/ +/* coding more than one distinct audio stream. */ + + n = &(st->n); + d__ = &(st->d__); + fpc = &(st->fpc); + l2buf = &(st->l2buf[0]); + l2sum1 = &(st->l2sum1); + l2ptr1 = &(st->l2ptr1); + l2ptr2 = &(st->l2ptr2); + lasti = &(st->lasti); + hyst = &(st->hyst); + + /* Parameter adjustments */ + if (osbuf) { + --osbuf; + } + if (pebuf) { + pebuf_offset = *sbufl; + pebuf -= pebuf_offset; + } + + /* Function Body */ + +/* The following line subtracted a hard-coded "180" from LASTI, */ +/* instead of using a variable like LFRAME or a constant like */ +/* MAXFRM. I changed it to LFRAME, for "generality". */ + if (*hyst) { + *lasti -= *lframe; + } + i__1 = *sbufh; + for (i__ = *sbufh - *lframe + 1; i__ <= i__1; ++i__) { +/* Compute FPC; Use old FPC on divide by zero; Clamp FPC to +/- 1. +*/ + *n = (pebuf[i__] * pebuf[i__ - 1] + (*n) * 63.f) / 64.f; +/* Computing 2nd power */ + r__1 = pebuf[i__ - 1]; + *d__ = (r__1 * r__1 + (*d__) * 63.f) / 64.f; + if ((*d__) != 0.f) { + if (abs(*n) > (*d__)) { + *fpc = r_sign(&c_b2, n); + } else { + *fpc = (*n) / (*d__); + } + } +/* Filter FPC */ +/* In order to allow L2SUM1 not to be saved from one invocation +of */ +/* this subroutine to the next, one could change the sequence of + */ +/* assignments below, up to the IF statement, to the following. + In */ +/* addition, the initial value of L2PTR2 should be changed to */ +/* L2WID/2 instead of L2WID/2+1. */ + +/* L2SUM1 = L2BUF(L2PTR2) */ +/* L2PTR2 = MOD(L2PTR2,L2WID)+1 */ +/* L2SUM1 = L2SUM1 - L2BUF(L2PTR2) + FPC */ +/* L2BUF(L2PTR2) = L2SUM1 */ + +/* * The following lines didn't change from the original: */ +/* L2SUM2 = L2BUF(L2PTR1) */ +/* L2BUF(L2PTR1) = FPC */ +/* L2PTR1 = MOD(L2PTR1,L2WID)+1 */ + + l2sum2 = l2buf[*l2ptr1 - 1]; + *l2sum1 = *l2sum1 - l2buf[*l2ptr2 - 1] + *fpc; + l2buf[*l2ptr2 - 1] = *l2sum1; + l2buf[*l2ptr1 - 1] = *fpc; + *l2ptr1 = *l2ptr1 % 16 + 1; + *l2ptr2 = *l2ptr2 % 16 + 1; + if ((r__1 = *l2sum1 - l2sum2, abs(r__1)) > 1.7f) { + if (! (*hyst)) { +/* Ignore if buffer full */ + if (*osptr <= *oslen) { + osbuf[*osptr] = i__ - 9; + ++(*osptr); + } + *hyst = TRUE_; + } + *lasti = i__; +/* After one onset detection, at least OSHYST sample times m +ust go */ +/* by before another is allowed to occur. */ + } else if ((*hyst) && i__ - *lasti >= 10) { + *hyst = FALSE_; + } + } + return 0; +} /* onset_ */ diff --git a/libs/codec/lpc10/pitsyn.c b/libs/codec/lpc10/pitsyn.c new file mode 100644 index 0000000000..30d6063776 --- /dev/null +++ b/libs/codec/lpc10/pitsyn.c @@ -0,0 +1,583 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/11/23 22:14:32 markster +Various warning cleanups + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:40:12 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:31:12 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int pitsyn_(integer *order, integer *voice, integer *pitch, real *rms, real *rc, integer *lframe, integer *ivuv, integer *ipiti, real *rmsi, real *rci, integer *nout, real *ratio, struct lpc10_decoder_state *st); +#endif + +/* ***************************************************************** */ + +/* PITSYN Version 53 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/11/23 22:14:32 markster +/* Various warning cleanups +/* +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:40:12 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:31:12 jaf + * Initial revision + * */ +/* Revision 1.2 1996/03/25 18:49:07 jaf */ +/* Added commments about which indices of array arguments are read or */ +/* written. */ + +/* Rearranged local variable declarations to indicate which need to be */ +/* saved from one invocation to the next. Added entry INITPITSYN to */ +/* reinitialize local state variables, if desired. */ + +/* Added lots of comments about proving that the maximum number of pitch */ +/* periods (NOUT) that can be returned is 16. The call to STOP that */ +/* could happen if NOUT got too large was removed as a result. */ + +/* Also proved that the total number of samples returned from N calls, */ +/* each with identical values of LFRAME, will always be in the range */ +/* N*LFRAME-MAXPIT+1 to N*LFRAME. */ + +/* Revision 1.1 1996/02/07 14:48:18 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* Synthesize a single pitch epoch */ + +/* Input: */ +/* ORDER - Synthesis order (number of RC's) */ +/* VOICE - Half frame voicing decisions */ +/* Indices 1 through 2 read. */ +/* LFRAME - Length of speech buffer */ +/* Input/Output: */ +/* PITCH - Pitch */ +/* This value should be in the range MINPIT (20) to MAXPIT */ +/* (156), inclusive. */ +/* PITCH can be modified under some conditions. */ +/* RMS - Energy (can be modified) */ +/* RMS is changed to 1 if the value passed in is less than 1. */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER can be temporarily overwritten with */ +/* RCO, and then replaced with original values, under some */ +/* conditions. */ +/* Output: */ +/* IVUV - Pitch epoch voicing decisions */ +/* Indices (I) of IVUV, IPITI, and RMSI are written, */ +/* and indices (J,I) of RCI are written, */ +/* where I ranges from 1 to NOUT, and J ranges from 1 to ORDER. */ +/* IPITI - Pitch epoch length */ +/* RMSI - Pitch epoch energy */ +/* RCI - Pitch epoch RC's */ +/* NOUT - Number of pitch periods in this frame */ +/* This is at least 0, at least 1 if MAXPIT .LT. LFRAME (this */ +/* is currently true on every call), and can never be more than */ +/* (LFRAME+MAXPIT-1)/PITCH, which is currently 16 with */ +/* LFRAME=180, MAXPIT=156, and PITCH .GE. 20, as SYNTHS */ +/* guarantees when it calls this subroutine. */ +/* RATIO - Previous to present energy ratio */ +/* Always assigned a value. */ + +/* Subroutine */ int pitsyn_(integer *order, integer *voice, + integer *pitch, real *rms, real *rc, integer *lframe, integer *ivuv, + integer *ipiti, real *rmsi, real *rci, integer *nout, real *ratio, + struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + real *rmso; + logical *first; + + /* System generated locals */ + integer rci_dim1 = 0, rci_offset, i__1, i__2; + real r__1; + + /* Builtin functions */ + double log(doublereal), exp(doublereal); + + /* Local variables */ + real alrn, alro, yarc[10], prop; + integer i__, j, vflag, jused, lsamp; + integer *jsamp; + real slope; + integer *ipito; + real uvpit; + integer ip, nl, ivoice; + integer *ivoico; + integer istart; + real *rco; + real xxy; + +/* Arguments */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/11/23 22:14:32 markster +/* Various warning cleanups +/* +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:40:12 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:31:12 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Local variables that need not be saved */ +/* LSAMP is initialized in the IF (FIRST) THEN clause, but it is */ +/* not used the first time through, and it is given a value before +*/ +/* use whenever FIRST is .FALSE., so it appears unnecessary to */ +/* assign it a value when FIRST is .TRUE. */ +/* Local state */ +/* FIRST - .TRUE. only on first call to PITSYN. */ +/* IVOICO - Previous VOICE(2) value. */ +/* IPITO - Previous PITCH value. */ +/* RMSO - Previous RMS value. */ +/* RCO - Previous RC values. */ + +/* JSAMP - If this routine is called N times with identical values of */ +/* LFRAME, then the total length of all pitch periods returned */ +/* is always N*LFRAME-JSAMP, and JSAMP is always in the range 0 +*/ +/* to MAXPIT-1 (see below for why this is so). Thus JSAMP is */ +/* the number of samples "left over" from the previous call to */ +/* PITSYN, that haven't been "used" in a pitch period returned */ +/* from this subroutine. Every time this subroutine is called, +*/ +/* it returns pitch periods with a total length of at most */ +/* LFRAME+JSAMP. */ + +/* IVOICO, IPITO, RCO, and JSAMP need not be assigned an initial value */ +/* with a DATA statement, because they are always initialized on the */ +/* first call to PITSYN. */ + +/* FIRST and RMSO should be initialized with DATA statements, because */ +/* even on the first call, they are used before being initialized. */ + /* Parameter adjustments */ + if (rc) { + --rc; + } + if (rci) { + rci_dim1 = *order; + rci_offset = rci_dim1 + 1; + rci -= rci_offset; + } + if (voice) { + --voice; + } + if (ivuv) { + --ivuv; + } + if (ipiti) { + --ipiti; + } + if (rmsi) { + --rmsi; + } + + /* Function Body */ + ivoico = &(st->ivoico); + ipito = &(st->ipito); + rmso = &(st->rmso); + rco = &(st->rco[0]); + jsamp = &(st->jsamp); + first = &(st->first_pitsyn); + + if (*rms < 1.f) { + *rms = 1.f; + } + if (*rmso < 1.f) { + *rmso = 1.f; + } + uvpit = 0.f; + *ratio = *rms / (*rmso + 8.f); + if (*first) { + lsamp = 0; + ivoice = voice[2]; + if (ivoice == 0) { + *pitch = *lframe / 4; + } + *nout = *lframe / *pitch; + *jsamp = *lframe - *nout * *pitch; + +/* SYNTHS only calls this subroutine with PITCH in the range +20 */ +/* to 156. LFRAME = MAXFRM = 180, so NOUT is somewhere in th +e */ +/* range 1 to 9. */ + +/* JSAMP is "LFRAME mod PITCH", so it is in the range 0 to */ +/* (PITCH-1), or 0 to MAXPIT-1=155, after the first call. */ + + i__1 = *nout; + for (i__ = 1; i__ <= i__1; ++i__) { + i__2 = *order; + for (j = 1; j <= i__2; ++j) { + rci[j + i__ * rci_dim1] = rc[j]; + } + ivuv[i__] = ivoice; + ipiti[i__] = *pitch; + rmsi[i__] = *rms; + } + *first = FALSE_; + } else { + vflag = 0; + lsamp = *lframe + *jsamp; + slope = (*pitch - *ipito) / (real) lsamp; + *nout = 0; + jused = 0; + istart = 1; + if (voice[1] == *ivoico && voice[2] == voice[1]) { + if (voice[2] == 0) { +/* SSUV - - 0 , 0 , 0 */ + *pitch = *lframe / 4; + *ipito = *pitch; + if (*ratio > 8.f) { + *rmso = *rms; + } + } +/* SSVC - - 1 , 1 , 1 */ + slope = (*pitch - *ipito) / (real) lsamp; + ivoice = voice[2]; + } else { + if (*ivoico != 1) { + if (*ivoico == voice[1]) { +/* UV2VC2 - - 0 , 0 , 1 */ + nl = lsamp - *lframe / 4; + } else { +/* UV2VC1 - - 0 , 1 , 1 */ + nl = lsamp - *lframe * 3 / 4; + } + ipiti[1] = nl / 2; + ipiti[2] = nl - ipiti[1]; + ivuv[1] = 0; + ivuv[2] = 0; + rmsi[1] = *rmso; + rmsi[2] = *rmso; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + rci[i__ + rci_dim1] = rco[i__ - 1]; + rci[i__ + (rci_dim1 << 1)] = rco[i__ - 1]; + rco[i__ - 1] = rc[i__]; + } + slope = 0.f; + *nout = 2; + *ipito = *pitch; + jused = nl; + istart = nl + 1; + ivoice = 1; + } else { + if (*ivoico != voice[1]) { +/* VC2UV1 - - 1 , 0 , 0 */ + lsamp = *lframe / 4 + *jsamp; + } else { +/* VC2UV2 - - 1 , 1 , 0 */ + lsamp = *lframe * 3 / 4 + *jsamp; + } + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + yarc[i__ - 1] = rc[i__]; + rc[i__] = rco[i__ - 1]; + } + ivoice = 1; + slope = 0.f; + vflag = 1; + } + } +/* Here is the value of most variables that are used below, depending +on */ +/* the values of IVOICO, VOICE(1), and VOICE(2). VOICE(1) and VOICE(2 +) */ +/* are input arguments, and IVOICO is the value of VOICE(2) on the */ +/* previous call (see notes for the IF (NOUT .NE. 0) statement near th +e */ +/* end). Each of these three values is either 0 or 1. These three */ +/* values below are given as 3-bit long strings, in the order IVOICO, +*/ +/* VOICE(1), and VOICE(2). It appears that the code above assumes tha +t */ +/* the bit sequences 010 and 101 never occur, but I wonder whether a +*/ +/* large enough number of bit errors in the channel could cause such a + */ +/* thing to happen, and if so, could that cause NOUT to ever go over 1 +1? */ + +/* Note that all of the 180 values in the table are really LFRAME, but + */ +/* 180 has fewer characters, and it makes the table a little more */ +/* concrete. If LFRAME is ever changed, keep this in mind. Similarly +, */ +/* 135's are 3*LFRAME/4, and 45's are LFRAME/4. If LFRAME is not a */ +/* multiple of 4, then the 135 for NL-JSAMP is actually LFRAME-LFRAME/ +4, */ +/* and the 45 for NL-JSAMP is actually LFRAME-3*LFRAME/4. */ + +/* Note that LSAMP-JSAMP is given as the variable. This was just for +*/ +/* brevity, to avoid adding "+JSAMP" to all of the column entries. */ +/* Similarly for NL-JSAMP. */ + +/* Variable | 000 001 011,010 111 110 100,101 */ +/* ------------+-------------------------------------------------- */ +/* ISTART | 1 NL+1 NL+1 1 1 1 */ +/* LSAMP-JSAMP | 180 180 180 180 135 45 */ +/* IPITO | 45 PITCH PITCH oldPITCH oldPITCH oldPITCH */ +/* SLOPE | 0 0 0 seebelow 0 0 */ +/* JUSED | 0 NL NL 0 0 0 */ +/* PITCH | 45 PITCH PITCH PITCH PITCH PITCH */ +/* NL-JSAMP | -- 135 45 -- -- -- */ +/* VFLAG | 0 0 0 0 1 1 */ +/* NOUT | 0 2 2 0 0 0 */ +/* IVOICE | 0 1 1 1 1 1 */ + +/* while_loop | once once once once twice twice */ + +/* ISTART | -- -- -- -- JUSED+1 JUSED+1 */ +/* LSAMP-JSAMP | -- -- -- -- 180 180 */ +/* IPITO | -- -- -- -- oldPITCH oldPITCH */ +/* SLOPE | -- -- -- -- 0 0 */ +/* JUSED | -- -- -- -- ?? ?? */ +/* PITCH | -- -- -- -- PITCH PITCH */ +/* NL-JSAMP | -- -- -- -- -- -- */ +/* VFLAG | -- -- -- -- 0 0 */ +/* NOUT | -- -- -- -- ?? ?? */ +/* IVOICE | -- -- -- -- 0 0 */ + + +/* UVPIT is always 0.0 on the first pass through the DO WHILE (.TRUE.) + */ +/* loop below. */ + +/* The only possible non-0 value of SLOPE (in column 111) is */ +/* (PITCH-IPITO)/FLOAT(LSAMP) */ + +/* Column 101 is identical to 100. Any good properties we can prove +*/ +/* for 100 will also hold for 101. Similarly for 010 and 011. */ + +/* SYNTHS calls this subroutine with PITCH restricted to the range 20 +to */ +/* 156. IPITO is similarly restricted to this range, after the first +*/ +/* call. IP below is also restricted to this range, given the */ +/* definitions of IPITO, SLOPE, UVPIT, and that I is in the range ISTA +RT */ +/* to LSAMP. */ + + while(TRUE_) { + +/* JUSED is the total length of all pitch periods curr +ently */ +/* in the output arrays, in samples. */ + +/* An invariant of the DO I = ISTART,LSAMP loop below, + under */ +/* the condition that IP is always in the range 1 thro +ugh */ +/* MAXPIT, is: */ + +/* (I - MAXPIT) .LE. JUSED .LE. (I-1) */ + +/* Note that the final value of I is LSAMP+1, so that +after */ +/* the DO loop is complete, we know: */ + +/* (LSAMP - MAXPIT + 1) .LE. JUSED .LE. LSAMP */ + + i__1 = lsamp; + for (i__ = istart; i__ <= i__1; ++i__) { + r__1 = *ipito + slope * i__; + ip = r__1 + .5f; + if (uvpit != 0.f) { + ip = uvpit; + } + if (ip <= i__ - jused) { + ++(*nout); + +/* The following check is no longer nece +ssary, now that */ +/* we can prove that NOUT will never go +over 16. */ + +/* IF (NOUT .GT. 16) STOP 'PITSYN: too many epochs' +*/ + + ipiti[*nout] = ip; + *pitch = ip; + ivuv[*nout] = ivoice; + jused += ip; + prop = (jused - ip / 2) / (real) lsamp; + i__2 = *order; + for (j = 1; j <= i__2; ++j) { + alro = log((rco[j - 1] + 1) / (1 - rco[j - 1])); + alrn = log((rc[j] + 1) / (1 - rc[j])); + xxy = alro + prop * (alrn - alro); + xxy = exp(xxy); + rci[j + *nout * rci_dim1] = (xxy - 1) / (xxy + 1); + } + rmsi[*nout] = log(*rmso) + prop * (log(*rms) - log(*rmso)); + rmsi[*nout] = exp(rmsi[*nout]); + } + } + if (vflag != 1) { + goto L100; + } + +/* I want to prove what range UVPIT must lie in after +the */ +/* assignments to it below. To do this, I must determ +ine */ +/* what range (LSAMP-ISTART) must lie in, after the */ +/* assignments to ISTART and LSAMP below. */ + +/* Let oldLSAMP be the value of LSAMP at this point in + the */ +/* execution. This is 135+JSAMP in state 110, or 45+J +SAMP in */ +/* states 100 or 101. */ + +/* Given the loop invariant on JUSED above, we know th +at: */ + +/* (oldLSAMP - MAXPIT + 1) .LE. JUSED .LE. oldLSAMP */ + +/* ISTART is one more than this. */ + +/* Let newLSAMP be the value assigned to LSAMP below. + This */ +/* is 180+JSAMP. Thus (newLSAMP-oldLSAMP) is either 4 +5 or */ +/* 135, depending on the state. */ + +/* Thus, the range of newLSAMP-ISTART is: */ + +/* (newLSAMP-(oldLSAMP+1)) .LE. newLSAMP-ISTART */ +/* .LE. (newLSAMP-(oldLSAMP - MAXPIT + 2)) */ + +/* or: */ + +/* 46 .LE. newLSAMP-ISTART .LE. 133+MAXPIT .EQ. 289 */ + +/* Therefore, UVPIT is in the range 23 to 144 after th +e first */ +/* assignment to UVPIT below, and after the conditiona +l */ +/* assignment, it is in the range 23 to 90. */ + +/* The important thing is that it is in the range 20 t +o 156, */ +/* so that in the loop above, IP is always in this ran +ge. */ + + vflag = 0; + istart = jused + 1; + lsamp = *lframe + *jsamp; + slope = 0.f; + ivoice = 0; + uvpit = (real) ((lsamp - istart) / 2); + if (uvpit > 90.f) { + uvpit /= 2; + } + *rmso = *rms; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + rc[i__] = yarc[i__ - 1]; + rco[i__ - 1] = yarc[i__ - 1]; + } + } +L100: + *jsamp = lsamp - jused; + } +/* Given that the maximum pitch period MAXPIT .LT. LFRAME (this is +*/ +/* currently true on every call, since SYNTHS always sets */ +/* LFRAME=180), NOUT will always be .GE. 1 at this point. */ + if (*nout != 0) { + *ivoico = voice[2]; + *ipito = *pitch; + *rmso = *rms; + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + rco[i__ - 1] = rc[i__]; + } + } + return 0; +} /* pitsyn_ */ diff --git a/libs/codec/lpc10/placea.c b/libs/codec/lpc10/placea.c new file mode 100644 index 0000000000..c0c7fa00cb --- /dev/null +++ b/libs/codec/lpc10/placea.c @@ -0,0 +1,242 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.2 2003/09/19 01:20:22 markster +Code cleanups (bug #66) + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.3 2001/04/12 21:27:53 markh +app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set. + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:07 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int placea_(integer *ipitch, integer *voibuf, integer *obound, integer *af, integer *vwin, integer *awin, integer *ewin, integer *lframe, integer *maxwin); +#endif + +/* *********************************************************************** */ + +/* PLACEA Version 48 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.2 2003/09/19 01:20:22 markster +/* Code cleanups (bug #66) +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.3 2001/04/12 21:27:53 markh +/* app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set. +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:31:07 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/19 20:41:55 jaf */ +/* Added some conditions satisfied by the output values in EWIN. */ + +/* Revision 1.4 1996/03/19 20:24:17 jaf */ +/* Added some conditions satisfied by the output values in AWIN. */ + +/* Revision 1.3 1996/03/18 21:40:04 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:43:09 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:48:31 jaf */ +/* Initial revision */ + + +/* *********************************************************************** */ +/* Input: */ +/* IPITCH */ +/* VOIBUF */ +/* Indices (2,AF-2), (1,AF-1), (2,AF-1), (1,AF), and (2,AF) read.*/ +/* All other indices untouched. */ +/* OBOUND */ +/* AF */ +/* VWIN */ +/* Indices (1,AF) and (2,AF) read. */ +/* All other indices untouched. */ +/* LFRAME */ +/* MAXWIN */ +/* Input/Output: */ +/* AWIN */ +/* Index (1,AF-1) read. */ +/* Indices (1,AF) and (2,AF) written, and then read. */ +/* All other indices untouched. */ +/* In all cases (except possibly one), the final values will */ +/* satisfy the condition: AWIN(2,AF)-AWIN(1,AF)+1 = MAXWIN. */ +/* In that other case, */ +/* AWIN(1,AF)=VWIN(1,AF) and AWIN(2,AF)=VWIN(2,AF). */ +/* Output: */ +/* EWIN */ +/* Indices (1,AF) and (2,AF) written. */ +/* All other indices untouched. */ +/* In all cases, the final values will satisfy the condition: */ +/* AWIN(1,AF) .LE. EWIN(1,AF) .LE. EWIN(2,AF) .LE. AWIN(2,AF) */ +/* In other words, the energy window is a sub-window of */ +/* the analysis window. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int placea_(integer *ipitch, integer *voibuf, integer * + obound, integer *af, integer *vwin, integer *awin, integer *ewin, + integer *lframe, integer *maxwin) +{ + /* System generated locals */ + real r__1; + + /* Builtin functions */ + integer i_nint(real *); + + /* Local variables */ + logical allv, winv; + integer i__, j, k, l, hrange; + logical ephase; + integer lrange; + +/* Arguments */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + ewin -= 3; + awin -= 3; + vwin -= 3; + --voibuf; + + /* Function Body */ + lrange = (*af - 2) * *lframe + 1; + hrange = *af * *lframe; +/* Place the Analysis window based on the voicing window */ +/* placement, onsets, tentative voicing decision, and pitch. */ + +/* Case 1: Sustained Voiced Speech */ +/* If the five most recent voicing decisions are */ +/* voiced, then the window is placed phase-synchronously with the */ +/* previous window, as close to the present voicing window if possible. +*/ +/* If onsets bound the voicing window, then preference is given to */ +/* a phase-synchronous placement which does not overlap these onsets. */ + +/* Case 2: Voiced Transition */ +/* If at least one voicing decision in AF is voicied, and there are no +*/ +/* onsets, then the window is placed as in case 1. */ + +/* Case 3: Unvoiced Speech or Onsets */ +/* If both voicing decisions in AF are unvoiced, or there are onsets, */ +/* then the window is placed coincident with the voicing window. */ + +/* Note: During phase-synchronous placement of windows, the length */ +/* is not altered from MAXWIN, since this would defeat the purpose */ +/* of phase-synchronous placement. */ +/* Check for case 1 and case 2 */ + allv = voibuf[((*af - 2) << 1) + 2] == 1; + allv = allv && voibuf[((*af - 1) << 1) + 1] == 1; + allv = allv && voibuf[((*af - 1) << 1) + 2] == 1; + allv = allv && voibuf[(*af << 1) + 1] == 1; + allv = allv && voibuf[(*af << 1) + 2] == 1; + winv = voibuf[(*af << 1) + 1] == 1 || voibuf[(*af << 1) + 2] == 1; + if (allv || (winv && *obound == 0)) { +/* APHASE: Phase synchronous window placement. */ +/* Get minimum lower index of the window. */ + i__ = (lrange + *ipitch - 1 - awin[((*af - 1) << 1) + 1]) / *ipitch; + i__ *= *ipitch; + i__ += awin[((*af - 1) << 1) + 1]; +/* L = the actual length of this frame's analysis window. */ + l = *maxwin; +/* Calculate the location where a perfectly centered window would star +t. */ + k = (vwin[(*af << 1) + 1] + vwin[(*af << 1) + 2] + 1 - l) / 2; +/* Choose the actual location to be the pitch multiple closest to this +. */ + r__1 = (real) (k - i__) / *ipitch; + awin[(*af << 1) + 1] = i__ + i_nint(&r__1) * *ipitch; + awin[(*af << 1) + 2] = awin[(*af << 1) + 1] + l - 1; +/* If there is an onset bounding the right of the voicing window and t +he */ +/* analysis window overlaps that, then move the analysis window backwa +rd */ +/* to avoid this onset. */ + if (*obound >= 2 && awin[(*af << 1) + 2] > vwin[(*af << 1) + 2]) { + awin[(*af << 1) + 1] -= *ipitch; + awin[(*af << 1) + 2] -= *ipitch; + } +/* Similarly for the left of the voicing window. */ + if ((*obound == 1 || *obound == 3) && awin[(*af << 1) + 1] < vwin[(* + af << 1) + 1]) { + awin[(*af << 1) + 1] += *ipitch; + awin[(*af << 1) + 2] += *ipitch; + } +/* If this placement puts the analysis window above HRANGE, then */ +/* move it backward an integer number of pitch periods. */ + while(awin[(*af << 1) + 2] > hrange) { + awin[(*af << 1) + 1] -= *ipitch; + awin[(*af << 1) + 2] -= *ipitch; + } +/* Similarly if the placement puts the analysis window below LRANGE. +*/ + while(awin[(*af << 1) + 1] < lrange) { + awin[(*af << 1) + 1] += *ipitch; + awin[(*af << 1) + 2] += *ipitch; + } +/* Make Energy window be phase-synchronous. */ + ephase = TRUE_; +/* Case 3 */ + } else { + awin[(*af << 1) + 1] = vwin[(*af << 1) + 1]; + awin[(*af << 1) + 2] = vwin[(*af << 1) + 2]; + ephase = FALSE_; + } +/* RMS is computed over an integer number of pitch periods in the analysis + */ +/*window. When it is not placed phase-synchronously, it is placed as clos +e*/ +/* as possible to onsets. */ + j = (awin[(*af << 1) + 2] - awin[(*af << 1) + 1] + 1) / *ipitch * *ipitch; + if (j == 0 || ! winv) { + ewin[(*af << 1) + 1] = vwin[(*af << 1) + 1]; + ewin[(*af << 1) + 2] = vwin[(*af << 1) + 2]; + } else if (! ephase && *obound == 2) { + ewin[(*af << 1) + 1] = awin[(*af << 1) + 2] - j + 1; + ewin[(*af << 1) + 2] = awin[(*af << 1) + 2]; + } else { + ewin[(*af << 1) + 1] = awin[(*af << 1) + 1]; + ewin[(*af << 1) + 2] = awin[(*af << 1) + 1] + j - 1; + } + return 0; +} /* placea_ */ + diff --git a/libs/codec/lpc10/placev.c b/libs/codec/lpc10/placev.c new file mode 100644 index 0000000000..11fadb4e42 --- /dev/null +++ b/libs/codec/lpc10/placev.c @@ -0,0 +1,275 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.3 2001/04/12 21:27:53 markh +app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set. + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:31:02 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int placev_(integer *osbuf, integer *osptr, integer *oslen, integer *obound, integer *vwin, integer *af, integer *lframe, integer *minwin, integer *maxwin, integer *dvwinl, integer *dvwinh); +#endif + +/* ****************************************************************** */ + +/* PLACEV Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.3 2001/04/12 21:27:53 markh +/* app_record now supports wildcards of sort so your output file is not overwritten every time it's run. File.h got a documentation update on the ast_fileexists to include the return call. Watch out for the placea.c placev.c code, it's updates have not been tested yet. Just a few parenthesis to make it compile nicer on newer gcc versions with all the -W flags set. +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:31:02 jaf + * Initial revision + * */ +/* Revision 1.6 1996/03/19 20:42:19 jaf */ +/* Added some conditions satisfied by the output values in VWIN. */ + +/* Revision 1.5 1996/03/19 18:37:56 jaf */ +/* Strengthened the specification of which indices of VWIN are read and */ +/* written. */ + +/* Revision 1.4 1996/03/15 16:38:33 jaf */ +/* One tiny comment added. */ + +/* Revision 1.3 1996/03/15 16:36:13 jaf */ +/* Added comments giving In/Out status of arguments. */ + +/* Revision 1.2 1996/03/12 23:56:01 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:48:39 jaf */ +/* Initial revision */ + + +/* ****************************************************************** */ + +/* Input: */ +/* OSBUF Buffer which holds sorted indexes of onsets */ +/* I believe that only indices 1 through OSPTR-1 can be read. */ +/* OSLEN */ +/* OSPTR Free pointer into OSBUF */ +/* AF */ +/* LFRAME */ +/* MINWIN */ +/* MAXWIN */ +/* DVWINL */ +/* DVWINH (This argument is never used. Should it be?) */ +/* Input/Output: */ +/* VWIN Buffer of Voicing Window Positions (Modified) */ +/* Index (2,AF-1) is read. */ +/* Indices (1,AF) and (2,AF) are written, */ +/* and then possibly read. */ +/* All other indices are unused. */ +/* In all cases, the final values will satsify the condition:*/ +/* VWIN(2,AF)-VWIN(1,AF)+1 .LE. MAXWIN */ +/* I'm not certain yet, but they may also satisfy: */ +/* MINWIN .LE. VWIN(2,AF)-VWIN(1,AF)+1 */ +/* Output: */ +/* OBOUND This variable is set by this procedure and used */ +/* in placing analysis windows (PLACEA). Bit 1 */ +/* indicates whether an onset bounds the left side */ +/* of the voicing window, and bit 2 indicates whether */ +/* an onset bounds the right side of the voicing window. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int placev_(integer *osbuf, integer *osptr, integer *oslen, + integer *obound, integer *vwin, integer *af, integer *lframe, integer + *minwin, integer *maxwin, integer *dvwinl, integer *dvwinh) +{ + /* System generated locals */ + integer i__1, i__2; + + /* Local variables */ + logical crit; + integer i__, q, osptr1, hrange, lrange; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Variables */ +/* LRANGE, HRANGE Range in which window is placed */ +/* OSPTR1 OSPTR excluding samples in 3F */ +/* Local state */ +/* None */ +/* Voicing Window Placement */ + +/* __________________ __________________ ______________ */ +/* | | | */ +/* | 1F | 2F | 3F ... */ +/* |__________________|__________________|______________ */ + +/* Previous | */ +/* Window | */ +/* ...________| */ + +/* | | */ +/* ------>| This window's placement range |<------ */ +/* | | */ + +/* There are three cases. Note that these are different from those */ +/* given in the LPC-10e phase 1 report. */ + +/* 1. If there are no onsets in this range, then the voicing window */ +/* is centered in the pitch window. If such a placement is not within +*/ +/* the window's placement range, then the window is placed in the left- +*/ +/* most portion of the placement range. Its length is always MAXWIN. */ + +/* 2. If the first onset is in 2F and there is sufficient room to place + */ +/* the window immediately before this onset, then the window is placed +*/ +/* there, and its length is set to the maximum possible under these */ +/* constraints. */ + +/* "Critical Region Exception": If there is another onset in 2F */ +/* such that a window can be placed between the two onsets, the */ +/* window is placed there (ie, as in case 3). */ + +/* 3. Otherwise, the window is placed immediately after the onset. The + */ +/* window's length */ +/* is the longest length that can fit in the range under these constraint +s,*/ +/* except that the window may be shortened even further to avoid overlapp +ing*/ +/* other onsets in the placement range. In any case, the window's length +*/ +/* is at least MINWIN. */ + +/* Note that the values of MINWIN and LFRAME must be chosen such */ +/* that case 2 = false implies case 3 = true. This means that */ +/* MINWIN <= LFRAME/2. If this were not the case, then a fourth case */ +/* would have to be added for when the window cannot fit either before +*/ +/* or after the onset. */ + +/* Note also that onsets which weren't in 2F last time may be in 1F this + */ +/* time, due to the filter delays in computing onsets. The result is tha +t*/ +/* occasionally a voicing window will overlap that onset. The only way +*/ +/* to circumvent this problem is to add more delay in processing input +*/ +/* speech. In the trade-off between delay and window-placement, window +*/ +/* placement lost. */ +/* Compute the placement range */ + /* Parameter adjustments */ + --osbuf; + vwin -= 3; + + /* Function Body */ +/* Computing MAX */ + i__1 = vwin[((*af - 1) << 1) + 2] + 1, i__2 = (*af - 2) * *lframe + 1; + lrange = max(i__1,i__2); + hrange = *af * *lframe; +/* Compute OSPTR1, so the following code only looks at relevant onsets. */ + for (osptr1 = *osptr - 1; osptr1 >= 1; --osptr1) { + if (osbuf[osptr1] <= hrange) { + goto L90; + } + } +L90: + ++osptr1; +/* Check for case 1 first (fast case): */ + if (osptr1 <= 1 || osbuf[osptr1 - 1] < lrange) { +/* Computing MAX */ + i__1 = vwin[((*af - 1) << 1) + 2] + 1; + vwin[(*af << 1) + 1] = max(i__1,*dvwinl); + vwin[(*af << 1) + 2] = vwin[(*af << 1) + 1] + *maxwin - 1; + *obound = 0; + } else { +/* Search backward in OSBUF for first onset in range. */ +/* This code relies on the above check being performed first. */ + for (q = osptr1 - 1; q >= 1; --q) { + if (osbuf[q] < lrange) { + goto L100; + } + } +L100: + ++q; +/* Check for case 2 (placement before onset): */ +/* Check for critical region exception: */ + i__1 = osptr1 - 1; + for (i__ = q + 1; i__ <= i__1; ++i__) { + if (osbuf[i__] - osbuf[q] >= *minwin) { + crit = TRUE_; + goto L105; + } + } + crit = FALSE_; +L105: +/* Computing MAX */ + i__1 = (*af - 1) * *lframe, i__2 = lrange + *minwin - 1; + if (! crit && osbuf[q] > max(i__1,i__2)) { + vwin[(*af << 1) + 2] = osbuf[q] - 1; +/* Computing MAX */ + i__1 = lrange, i__2 = vwin[(*af << 1) + 2] - *maxwin + 1; + vwin[(*af << 1) + 1] = max(i__1,i__2); + *obound = 2; +/* Case 3 (placement after onset) */ + } else { + vwin[(*af << 1) + 1] = osbuf[q]; +L110: + ++q; + if (q >= osptr1) { + goto L120; + } + if (osbuf[q] > vwin[(*af << 1) + 1] + *maxwin) { + goto L120; + } + if (osbuf[q] < vwin[(*af << 1) + 1] + *minwin) { + goto L110; + } + vwin[(*af << 1) + 2] = osbuf[q] - 1; + *obound = 3; + return 0; +L120: +/* Computing MIN */ + i__1 = vwin[(*af << 1) + 1] + *maxwin - 1; + vwin[(*af << 1) + 2] = min(i__1,hrange); + *obound = 1; + } + } + return 0; +} /* placev_ */ + diff --git a/libs/codec/lpc10/preemp.c b/libs/codec/lpc10/preemp.c new file mode 100644 index 0000000000..a1dfb306f2 --- /dev/null +++ b/libs/codec/lpc10/preemp.c @@ -0,0 +1,144 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:30:58 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int preemp_(real *inbuf, real *pebuf, integer *nsamp, real *coef, real *z__); +#endif + +/* ******************************************************************* */ + +/* PREEMP Version 55 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:30:58 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/14 23:16:29 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/11 23:23:34 jaf */ +/* Added a bunch of comments to an otherwise simple subroutine. */ + +/* Revision 1.1 1996/02/07 14:48:48 jaf */ +/* Initial revision */ + + +/* ******************************************************************* */ + +/* Preemphasize speech with a single-zero filter. */ +/* (When coef = .9375, preemphasis is as in LPC43.) */ + +/* Inputs: */ +/* NSAMP - Number of samples to filter */ +/* INBUF - Input speech buffer */ +/* Indices 1 through NSAMP are read. */ +/* COEF - Preemphasis coefficient */ +/* Input/Output: */ +/* Z - Filter state */ +/* Output: */ +/* PEBUF - Preemphasized speech buffer (can be equal to INBUF) */ +/* Indices 1 through NSAMP are modified. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int preemp_(real *inbuf, real *pebuf, integer *nsamp, real * + coef, real *z__) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + real temp; + integer i__; + +/* Arguments */ +/* Local variables */ + +/* None of these need to have their values saved from one */ +/* invocation to the next. */ + +/* Logically, this subroutine computes the output sequence */ +/* pebuf(1:nsamp) defined by: */ + +/* pebuf(i) = inbuf(i) - coef * inbuf(i-1) */ + +/* where inbuf(0) is defined by the value of z given as input to */ +/* this subroutine. */ + +/* What is this filter's frequency response and phase response? */ + +/* Why is this filter applied to the speech? */ + +/* Could it be more efficient to apply multiple filters */ +/* simultaneously, by combining them into one equivalent filter? */ + +/* Are there ever cases when "factoring" one high-order filter into +*/ +/* multiple smaller-order filter actually reduces the number of */ +/* arithmetic operations needed to perform them? */ +/* When I first read this subroutine, I didn't understand why the */ +/* variable temp was used. It seemed that the statements in the do +*/ +/* loop could be replaced with the following: */ + +/* pebuf(i) = inbuf(i) - coef * z */ +/* z = inbuf(i) */ + +/* The reason for temp is so that even if pebuf and inbuf are the */ +/* same arrays in memory (i.e., they are aliased), then this */ +/* subroutine will still work correctly. I didn't realize this */ +/* until seeing the comment after PEBUF above that says "(can be */ +/* equal to INBUF)". */ + /* Parameter adjustments */ + --pebuf; + --inbuf; + + /* Function Body */ + i__1 = *nsamp; + for (i__ = 1; i__ <= i__1; ++i__) { + temp = inbuf[i__] - *coef * *z__; + *z__ = inbuf[i__]; + pebuf[i__] = temp; +/* L10: */ + } + return 0; +} /* preemp_ */ + diff --git a/libs/codec/lpc10/prepro.c b/libs/codec/lpc10/prepro.c new file mode 100644 index 0000000000..d535a0bad7 --- /dev/null +++ b/libs/codec/lpc10/prepro.c @@ -0,0 +1,116 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:40:51 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:54 jaf + * Initial revision + * + */ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int prepro_(real *speech, integer *length, + struct lpc10_encoder_state *st); +/*:ref: hp100_ 14 3 6 4 4 */ +/*:ref: inithp100_ 14 0 */ +#endif + +/* Table of constant values */ + +static integer c__1 = 1; + +/* ********************************************************************* */ + +/* PREPRO Version 48 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:40:51 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:54 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/14 23:22:56 jaf */ +/* Added comments about when INITPREPRO should be used. */ + +/* Revision 1.2 1996/03/14 23:09:27 jaf */ +/* Added an entry named INITPREPRO that initializes the local state of */ +/* this subroutine, and those it calls (if any). */ + +/* Revision 1.1 1996/02/07 14:48:54 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Pre-process input speech: */ + +/* Inputs: */ +/* LENGTH - Number of SPEECH samples */ +/* Input/Output: */ +/* SPEECH(LENGTH) - Speech data. */ +/* Indices 1 through LENGTH are read and modified. */ + +/* This subroutine has no local state maintained from one call to the */ +/* next, but HP100 does. If you want to switch to using a new audio */ +/* stream for this filter, or reinitialize its state for any other */ +/* reason, call the ENTRY INITPREPRO. */ + +/* Subroutine */ int prepro_(real *speech, integer *length, + struct lpc10_encoder_state *st) +{ + extern /* Subroutine */ int hp100_(real *, integer *, integer *, struct lpc10_encoder_state *); + +/* Arguments */ +/* High Pass Filter at 100 Hz */ + /* Parameter adjustments */ + if (speech) { + --speech; + } + + /* Function Body */ + hp100_(&speech[1], &c__1, length, st); + return 0; +} /* prepro_ */ diff --git a/libs/codec/lpc10/random.c b/libs/codec/lpc10/random.c new file mode 100644 index 0000000000..4b8b3fc38d --- /dev/null +++ b/libs/codec/lpc10/random.c @@ -0,0 +1,125 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:41:32 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:49 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern integer random_(struct lpc10_decoder_state *st); +#endif + +/* ********************************************************************** */ + +/* RANDOM Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:41:32 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:49 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/20 16:13:54 jaf */ +/* Rearranged comments a little bit, and added comments explaining that */ +/* even though there is local state here, there is no need to create an */ +/* ENTRY for reinitializing it. */ + +/* Revision 1.2 1996/03/14 22:25:29 jaf */ +/* Just rearranged the comments and local variable declarations a bit. */ + +/* Revision 1.1 1996/02/07 14:49:01 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Pseudo random number generator based on Knuth, Vol 2, p. 27. */ + +/* Function Return: */ +/* RANDOM - Integer variable, uniformly distributed over -32768 to 32767 */ + +/* This subroutine maintains local state from one call to the next. */ +/* In the context of the LPC10 coder, there is no reason to reinitialize */ +/* this local state when switching between audio streams, because its */ +/* results are only used to generate noise for unvoiced frames. */ + +integer random_(struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + integer *j; + integer *k; + shortint *y; + + /* System generated locals */ + integer ret_val; + +/* Parameters/constants */ +/* Local state */ +/* The following is a 16 bit 2's complement addition, */ +/* with overflow checking disabled */ + + j = &(st->j); + k = &(st->k); + y = &(st->y[0]); + + y[*k - 1] += y[*j - 1]; + ret_val = y[*k - 1]; + --(*k); + if (*k <= 0) { + *k = 5; + } + --(*j); + if (*j <= 0) { + *j = 5; + } + return ret_val; +} /* random_ */ + diff --git a/libs/codec/lpc10/rcchk.c b/libs/codec/lpc10/rcchk.c new file mode 100644 index 0000000000..00ae8e4da8 --- /dev/null +++ b/libs/codec/lpc10/rcchk.c @@ -0,0 +1,119 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:30:41 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int rcchk_(integer *order, real *rc1f, real *rc2f); +#endif + +/* ********************************************************************* */ + +/* RCCHK Version 45G */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:30:41 jaf + * Initial revision + * */ +/* Revision 1.4 1996/03/27 18:13:47 jaf */ +/* Commented out a call to subroutine ERROR. */ + +/* Revision 1.3 1996/03/18 15:48:53 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 16:55:22 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:49:08 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Check RC's, repeat previous frame's RC's if unstable */ + +/* Input: */ +/* ORDER - Number of RC's */ +/* RC1F - Previous frame's RC's */ +/* Indices 1 through ORDER may be read. */ +/* Input/Output: */ +/* RC2F - Present frame's RC's */ +/* Indices 1 through ORDER may be read, and written. */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int rcchk_(integer *order, real *rc1f, real *rc2f) +{ + /* System generated locals */ + integer i__1; + real r__1; + + /* Local variables */ + integer i__; + +/* Arguments */ +/* Local variables that need not be saved */ + /* Parameter adjustments */ + --rc2f; + --rc1f; + + /* Function Body */ + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + if ((r__1 = rc2f[i__], abs(r__1)) > .99f) { + goto L10; + } + } + return 0; +/* Note: In version embedded in other software, all calls to ERROR +*/ +/* should probably be removed. */ +L10: + +/* This call to ERROR is only needed for debugging purposes. */ + +/* CALL ERROR('RCCHK',2,I) */ + i__1 = *order; + for (i__ = 1; i__ <= i__1; ++i__) { + rc2f[i__] = rc1f[i__]; + } + return 0; +} /* rcchk_ */ + diff --git a/libs/codec/lpc10/synths.c b/libs/codec/lpc10/synths.c new file mode 100644 index 0000000000..722ceb592f --- /dev/null +++ b/libs/codec/lpc10/synths.c @@ -0,0 +1,425 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/09/27 02:45:37 markster +Fix various compiler warnings (bug #322) + +Revision 1.2 2003/09/27 02:45:37 markster +Fix various compiler warnings (bug #322) + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:39 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:42:59 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:33 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int synths_(integer *voice, integer *pitch, real *rms, real *rc, real *speech, integer *k, struct lpc10_decoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: pitsyn_ 14 12 4 4 4 6 6 4 4 4 6 6 4 6 */ +/*:ref: irc2pc_ 14 5 6 6 4 6 6 */ +/*:ref: bsynz_ 14 7 6 4 4 6 6 6 6 */ +/*:ref: deemp_ 14 2 6 4 */ +/*:ref: initpitsyn_ 14 0 */ +/*:ref: initbsynz_ 14 0 */ +/*:ref: initdeemp_ 14 0 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/* Table of constant values */ + +static real c_b2 = .7f; + +/* ***************************************************************** */ + +/* SYNTHS Version 54 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/09/27 02:45:37 markster +/* Fix various compiler warnings (bug #322) +/* +/* Revision 1.2 2003/09/27 02:45:37 markster +/* Fix various compiler warnings (bug #322) +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:42:59 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:33 jaf + * Initial revision + * */ +/* Revision 1.5 1996/03/26 19:31:58 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.4 1996/03/25 19:41:01 jaf */ +/* Changed so that MAXFRM samples are always returned in the output array */ +/* SPEECH. */ + +/* This required delaying the returned samples by MAXFRM sample times, */ +/* and remembering any "left over" samples returned by PITSYN from one */ +/* call of SYNTHS to the next. */ + +/* Changed size of SPEECH from 2*MAXFRM to MAXFRM. Removed local */ +/* variable SOUT. Added local state variables BUF and BUFLEN. */ + +/* Revision 1.3 1996/03/25 19:20:10 jaf */ +/* Added comments about the range of possible return values for argument */ +/* K, and increased the size of the arrays filled in by PITSYN from 11 to */ +/* 16, as has been already done inside of PITSYN. */ + +/* Revision 1.2 1996/03/22 00:18:18 jaf */ +/* Added comments explaining meanings of input and output parameters, and */ +/* indicating which array indices can be read or written. */ + +/* Added entry INITSYNTHS, which does nothing except call the */ +/* corresponding initialization entries for subroutines PITSYN, BSYNZ, */ +/* and DEEMP. */ + +/* Revision 1.1 1996/02/07 14:49:44 jaf */ +/* Initial revision */ + + +/* ***************************************************************** */ + +/* The note below is from the distributed version of the LPC10 coder. */ +/* The version of the code below has been modified so that SYNTHS always */ +/* has a constant frame length output of MAXFRM. */ + +/* Also, BSYNZ and DEEMP need not be modified to work on variable */ +/* positions within an array. It is only necessary to pass the first */ +/* index desired as the array argument. What actually gets passed is the */ +/* address of that array position, which the subroutine treats as the */ +/* first index of the array. */ + +/* This technique is used in subroutine ANALYS when calling PREEMP, so it */ +/* appears that multiple people wrote different parts of this LPC10 code, */ +/* and that they didn't necessarily have equivalent knowledge of Fortran */ +/* (not surprising). */ + +/* NOTE: There is excessive buffering here, BSYNZ and DEEMP should be */ +/* changed to operate on variable positions within SOUT. Also, */ +/* the output length parameter is bogus, and PITSYN should be */ +/* rewritten to allow a constant frame length output. */ + +/* Input: */ +/* VOICE - Half frame voicing decisions */ +/* Indices 1 through 2 read. */ +/* Input/Output: */ +/* PITCH - Pitch */ +/* PITCH is restricted to range 20 to 156, inclusive, */ +/* before calling subroutine PITSYN, and then PITSYN */ +/* can modify it further under some conditions. */ +/* RMS - Energy */ +/* Only use is for debugging, and passed to PITSYN. */ +/* See comments there for how it can be modified. */ +/* RC - Reflection coefficients */ +/* Indices 1 through ORDER restricted to range -.99 to .99, */ +/* before calling subroutine PITSYN, and then PITSYN */ +/* can modify it further under some conditions. */ +/* Output: */ +/* SPEECH - Synthesized speech samples. */ +/* Indices 1 through the final value of K are written. */ +/* K - Number of samples placed into array SPEECH. */ +/* This is always MAXFRM. */ + +/* Subroutine */ int synths_(integer *voice, integer *pitch, real * + rms, real *rc, real *speech, integer *k, struct lpc10_decoder_state *st) +{ + /* Initialized data */ + + real *buf; + integer *buflen; + + /* System generated locals */ + integer i__1; + real r__1, r__2; + + /* Local variables */ + real rmsi[16]; + integer nout, ivuv[16], i__, j; + extern /* Subroutine */ int deemp_(real *, integer *, struct lpc10_decoder_state *); + real ratio; + integer ipiti[16]; + real g2pass; + real pc[10]; + extern /* Subroutine */ int pitsyn_(integer *, integer *, integer *, real + *, real *, integer *, integer *, integer *, real *, real *, + integer *, real *, struct lpc10_decoder_state *); + real rci[160] /* was [10][16] */; + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/09/27 02:45:37 markster +/* Fix various compiler warnings (bug #322) +/* +/* Revision 1.2 2003/09/27 02:45:37 markster +/* Fix various compiler warnings (bug #322) +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:42:59 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:33 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:03:47 jaf */ +/* Removed definitions for any constants that were no longer used. */ + +/* Revision 1.2 1996/03/26 19:34:33 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:43:51 jaf */ +/* Initial revision */ + +/* LPC Configuration parameters: */ +/* Frame size, Prediction order, Pitch period */ +/* Arguments */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/09/27 02:45:37 markster +/* Fix various compiler warnings (bug #322) +/* +/* Revision 1.2 2003/09/27 02:45:37 markster +/* Fix various compiler warnings (bug #322) +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:39 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:42:59 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_decoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_decoder_state(). + * + * Revision 1.1 1996/08/19 22:30:33 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Parameters/constants */ +/* Local variables that need not be saved */ +/* Local state */ +/* BUF is a buffer of speech samples that would have been returned +*/ +/* by the older version of SYNTHS, but the newer version doesn't, */ +/* so that the newer version can always return MAXFRM samples on */ +/* every call. This has the effect of delaying the return of */ +/* samples for one additional frame time. */ + +/* Indices 1 through BUFLEN contain samples that are left over from +*/ +/* the last call to SYNTHS. Given the way that PITSYN works, */ +/* BUFLEN should always be in the range MAXFRM-MAXPIT+1 through */ +/* MAXFRM, inclusive, after a call to SYNTHS is complete. */ + +/* On the first call to SYNTHS (or the first call after */ +/* reinitializing with the entry INITSYNTHS), BUFLEN is MAXFRM, and +*/ +/* a frame of silence is always returned. */ + /* Parameter adjustments */ + if (voice) { + --voice; + } + if (rc) { + --rc; + } + if (speech) { + --speech; + } + + /* Function Body */ + buf = &(st->buf[0]); + buflen = &(st->buflen); + +/* Computing MAX */ + i__1 = min(*pitch,156); + *pitch = max(i__1,20); + i__1 = contrl_1.order; + for (i__ = 1; i__ <= i__1; ++i__) { +/* Computing MAX */ +/* Computing MIN */ + r__2 = rc[i__]; + r__1 = min(r__2,.99f); + rc[i__] = max(r__1,-.99f); + } + pitsyn_(&contrl_1.order, &voice[1], pitch, rms, &rc[1], &contrl_1.lframe, + ivuv, ipiti, rmsi, rci, &nout, &ratio, st); + if (nout > 0) { + i__1 = nout; + for (j = 1; j <= i__1; ++j) { + +/* Add synthesized speech for pitch period J to the en +d of */ +/* BUF. */ + + irc2pc_(&rci[j * 10 - 10], pc, &contrl_1.order, &c_b2, &g2pass); + bsynz_(pc, &ipiti[j - 1], &ivuv[j - 1], &buf[*buflen], &rmsi[j - 1] + , &ratio, &g2pass, st); + deemp_(&buf[*buflen], &ipiti[j - 1], st); + *buflen += ipiti[j - 1]; + } + +/* Copy first MAXFRM samples from BUF to output array SPEECH +*/ +/* (scaling them), and then remove them from the beginning of + */ +/* BUF. */ + + for (i__ = 1; i__ <= 180; ++i__) { + speech[i__] = buf[i__ - 1] / 4096.f; + } + *k = 180; + *buflen += -180; + i__1 = *buflen; + for (i__ = 1; i__ <= i__1; ++i__) { + buf[i__ - 1] = buf[i__ + 179]; + } + } + return 0; +} /* synths_ */ diff --git a/libs/codec/lpc10/tbdm.c b/libs/codec/lpc10/tbdm.c new file mode 100644 index 0000000000..aaca148156 --- /dev/null +++ b/libs/codec/lpc10/tbdm.c @@ -0,0 +1,188 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:40 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:30:26 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int tbdm_(real *speech, integer *lpita, integer *tau, integer *ltau, real *amdf, integer *minptr, integer *maxptr, integer *mintau); +/*:ref: difmag_ 14 8 6 4 4 4 4 6 4 4 */ +#endif + +/* ********************************************************************** */ + +/* TBDM Version 49 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:40 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:30:26 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/18 22:14:00 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 14:48:37 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:49:54 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/*TURBO DIFMAG: Compute High Resolution Average Magnitude Difference Function +*/ + +/* Note: There are several constants in here that appear to depend on a */ +/* particular TAU table. That's not a problem for the LPC10 coder, but */ +/* watch out if you change the contents of TAU in the subroutine ANALYS. */ + +/* Input: */ +/* SPEECH - Low pass filtered speech */ +/* Indices 1 through MAX+LPITA-1 are read, where: */ +/* MAX = (TAU(LTAU)-TAU(1))/2+1 */ +/* (If TAU(1) .LT. 39, then larger indices could be read */ +/* by the last call to DIFMAG below.) */ +/* LPITA - Length of speech buffer */ +/* TAU - Table of lags, sorted in increasing order. */ +/* Indices 1 through LTAU read. */ +/* LTAU - Number of lag values to compute */ +/* Output: */ +/* AMDF - Average Magnitude Difference for each lag in TAU */ +/* Indices 1 through LTAU written, and several might then be read.*/ +/* MINPTR - Index of minimum AMDF value */ +/* MAXPTR - Index of maximum AMDF value within +/- 1/2 octave of min */ +/* MINTAU - Lag corresponding to minimum AMDF value */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int tbdm_(real *speech, integer *lpita, integer *tau, + integer *ltau, real *amdf, integer *minptr, integer *maxptr, integer * + mintau) +{ + /* System generated locals */ + integer i__1, i__2, i__3, i__4; + + /* Local variables */ + real amdf2[6]; + integer minp2, ltau2, maxp2, i__; + extern /* Subroutine */ int difmag_(real *, integer *, integer *, integer + *, integer *, real *, integer *, integer *); + integer minamd, ptr, tau2[6]; + +/* Arguments */ +/* REAL SPEECH(LPITA+TAU(LTAU)), AMDF(LTAU) */ +/* Stupid TOAST doesn't understand expressions */ +/* Local variables that need not be saved */ +/* Local state */ +/* None */ +/* Compute full AMDF using log spaced lags, find coarse minimum */ + /* Parameter adjustments */ + --speech; + --amdf; + --tau; + + /* Function Body */ + difmag_(&speech[1], lpita, &tau[1], ltau, &tau[*ltau], &amdf[1], minptr, + maxptr); + *mintau = tau[*minptr]; + minamd = amdf[*minptr]; +/* Build table containing all lags within +/- 3 of the AMDF minimum */ +/* excluding all that have already been computed */ + ltau2 = 0; + ptr = *minptr - 2; +/* Computing MAX */ + i__1 = *mintau - 3; +/* Computing MIN */ + i__3 = *mintau + 3, i__4 = tau[*ltau] - 1; + i__2 = min(i__3,i__4); + for (i__ = max(i__1,41); i__ <= i__2; ++i__) { + while(tau[ptr] < i__) { + ++ptr; + } + if (tau[ptr] != i__) { + ++ltau2; + tau2[ltau2 - 1] = i__; + } + } +/* Compute AMDF of the new lags, if there are any, and choose one */ +/* if it is better than the coarse minimum */ + if (ltau2 > 0) { + difmag_(&speech[1], lpita, tau2, <au2, &tau[*ltau], amdf2, &minp2, & + maxp2); + if (amdf2[minp2 - 1] < (real) minamd) { + *mintau = tau2[minp2 - 1]; + minamd = amdf2[minp2 - 1]; + } + } +/* Check one octave up, if there are any lags not yet computed */ + if (*mintau >= 80) { + i__ = *mintau / 2; + if ((i__ & 1) == 0) { + ltau2 = 2; + tau2[0] = i__ - 1; + tau2[1] = i__ + 1; + } else { + ltau2 = 1; + tau2[0] = i__; + } + difmag_(&speech[1], lpita, tau2, <au2, &tau[*ltau], amdf2, &minp2, & + maxp2); + if (amdf2[minp2 - 1] < (real) minamd) { + *mintau = tau2[minp2 - 1]; + minamd = amdf2[minp2 - 1]; + *minptr += -20; + } + } +/* Force minimum of the AMDF array to the high resolution minimum */ + amdf[*minptr] = (real) minamd; +/* Find maximum of AMDF within 1/2 octave of minimum */ +/* Computing MAX */ + i__2 = *minptr - 5; + *maxptr = max(i__2,1); +/* Computing MIN */ + i__1 = *minptr + 5; + i__2 = min(i__1,*ltau); + for (i__ = *maxptr + 1; i__ <= i__2; ++i__) { + if (amdf[i__] > amdf[*maxptr]) { + *maxptr = i__; + } + } + return 0; +} /* tbdm_ */ + diff --git a/libs/codec/lpc10/voicin.c b/libs/codec/lpc10/voicin.c new file mode 100644 index 0000000000..dc277e5ca0 --- /dev/null +++ b/libs/codec/lpc10/voicin.c @@ -0,0 +1,786 @@ +/* + +$Log$ +Revision 1.16 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.15 2003/11/23 22:14:32 markster +Various warning cleanups + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:40 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.2 1996/08/20 20:45:00 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:14 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int voicin_(integer *vwin, real *inbuf, real *lpbuf, integer *buflim, integer *half, real *minamd, real *maxamd, integer *mintau, real *ivrc, integer *obound, integer *voibuf, integer *af, struct lpc10_encoder_state *st); +/* comlen contrl_ 12 */ +/*:ref: vparms_ 14 14 4 6 6 4 4 6 4 4 4 4 6 6 6 6 */ +#endif + +/* Common Block Declarations */ + +extern struct { + integer order, lframe; + logical corrp; +} contrl_; + +#define contrl_1 contrl_ + +/****************************************************************************/ + +/* VOICIN Version 52 */ + +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/11/23 22:14:32 markster +/* Various warning cleanups +/* +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:40 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:45:00 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:14 jaf + * Initial revision + * */ +/* Revision 1.10 1996/03/29 17:59:14 jaf */ +/* Avoided using VALUE(9), although it shouldn't affect the function of */ +/* the code at all, because it was always multiplied by VDC(9,SNRL), */ +/* which is 0 for all values of SNRL. Still, if VALUE(9) had an initial */ +/* value of IEEE NaN, it might cause trouble (I don't know how IEEE */ +/* defines Nan * 0. It should either be NaN or 0.) */ + +/* Revision 1.9 1996/03/29 17:54:46 jaf */ +/* Added a few comments about the accesses made to argument array VOIBUF */ +/* and the local saved array VOICE. */ + +/* Revision 1.8 1996/03/27 18:19:54 jaf */ +/* Added an assignment to VSTATE that does not affect the function of the */ +/* program at all. The only reason I put it in was so that the tracing */ +/* statements at the end, when enabled, will print a consistent value for */ +/* VSTATE when HALF .EQ. 1, rather than a garbage value that could change */ +/* from one call to the next. */ + +/* Revision 1.7 1996/03/26 20:00:06 jaf */ +/* Removed the inclusion of the file "vcomm.fh", and put its contents */ +/* into this file. It was included nowhere else but here. */ + +/* Revision 1.6 1996/03/26 19:38:09 jaf */ +/* Commented out trace statements. */ + +/* Revision 1.5 1996/03/19 20:43:45 jaf */ +/* Added comments about which indices of OBOUND and VOIBUF can be */ +/* accessed, and whether they are read or written. VOIBUF is fairly */ +/* messy. */ + +/* Revision 1.4 1996/03/19 15:00:58 jaf */ +/* Moved the DATA statements for the *VDC* variables later, as it is */ +/* apparently illegal to have DATA statements before local variable */ +/* declarations. */ + +/* Revision 1.3 1996/03/19 00:10:49 jaf */ +/* Heavily commented the local variables that are saved from one */ +/* invocation to the next, and how the local variable FIRST is used to */ +/* avoid the need to assign most of them initial values with DATA */ +/* statements. */ + +/* A few should be initialized, but aren't. I've guessed initial values */ +/* for two of these, SFBUE and SLBUE, and I've convinced myself that for */ +/* VOICE, the effects of uninitialized values will die out after 2 or 3 */ +/* frame times. It would still be good to choose initial values for */ +/* these, but I don't know what reasonable values would be (0 comes to */ +/* mind). */ + +/* Revision 1.2 1996/03/13 16:09:28 jaf */ +/* Comments added explaining which of the local variables of this */ +/* subroutine need to be saved from one invocation to the next, and which */ +/* do not. */ + +/* WARNING! Some of them that should are never given initial values in */ +/* this code. Hopefully, Fortran 77 defines initial values for them, but */ +/* even so, giving them explicit initial values is preferable. */ + +/* WARNING! VALUE(9) is used, but never assigned a value. It should */ +/* probably be eliminated from the code. */ + +/* Revision 1.1 1996/02/07 14:50:28 jaf */ +/* Initial revision */ + + +/****************************************************************************/ + +/* Voicing Detection (VOICIN) makes voicing decisions for each half */ +/* frame of input speech. Tentative voicing decisions are made two frames*/ +/* in the future (2F) for each half frame. These decisions are carried */ +/* through one frame in the future (1F) to the present (P) frame where */ +/* they are examined and smoothed, resulting in the final voicing */ +/* decisions for each half frame. */ +/* The voicing parameter (signal measurement) column vector (VALUE) */ +/* is based on a rectangular window of speech samples determined by the */ +/* window placement algorithm. The voicing parameter vector contains the*/ +/* AMDF windowed maximum-to-minimum ratio, the zero crossing rate, energy*/ +/* measures, reflection coefficients, and prediction gains. The voicing */ +/* window is placed to avoid contamination of the voicing parameter vector*/ +/* with speech onsets. */ +/* The input signal is then classified as unvoiced (including */ +/* silence) or voiced. This decision is made by a linear discriminant */ +/* function consisting of a dot product of the voicing decision */ +/* coefficient (VDC) row vector with the measurement column vector */ +/* (VALUE). The VDC vector is 2-dimensional, each row vector is optimized*/ +/* for a particular signal-to-noise ratio (SNR). So, before the dot */ +/* product is performed, the SNR is estimated to select the appropriate */ +/* VDC vector. */ +/* The smoothing algorithm is a modified median smoother. The */ +/* voicing discriminant function is used by the smoother to determine how*/ +/* strongly voiced or unvoiced a signal is. The smoothing is further */ +/* modified if a speech onset and a voicing decision transition occur */ +/* within one half frame. In this case, the voicing decision transition */ +/* is extended to the speech onset. For transmission purposes, there are*/ +/* constraints on the duration and transition of voicing decisions. The */ +/* smoother takes these constraints into account. */ +/* Finally, the energy estimates are updated along with the dither */ +/* threshold used to calculate the zero crossing rate (ZC). */ + +/* Inputs: */ +/* VWIN - Voicing window limits */ +/* The indices read of arrays VWIN, INBUF, LPBUF, and BUFLIM */ +/* are the same as those read by subroutine VPARMS. */ +/* INBUF - Input speech buffer */ +/* LPBUF - Low-pass filtered speech buffer */ +/* BUFLIM - INBUF and LPBUF limits */ +/* HALF - Present analysis half frame number */ +/* MINAMD - Minimum value of the AMDF */ +/* MAXAMD - Maximum value of the AMDF */ +/* MINTAU - Pointer to the lag of the minimum AMDF value */ +/* IVRC(2) - Inverse filter's RC's */ +/* Only index 2 of array IVRC read under normal operation. */ +/* (Index 1 is also read when debugging is turned on.) */ +/* OBOUND - Onset boundary descriptions */ +/* Indices 1 through 3 read if (HALF .NE. 1), otherwise untouched. +*/ +/* AF - The analysis frame number */ +/* Output: */ +/* VOIBUF(2,0:AF) - Buffer of voicing decisions */ +/* Index (HALF,3) written. */ +/* If (HALF .EQ. 1), skip down to "Read (HALF,3)" below. */ +/* Indices (1,2), (2,1), (1,2), and (2,2) read. */ +/* One of the following is then done: */ +/* read (1,3) and possibly write (1,2) */ +/* read (1,3) and write (1,2) or (2,2) */ +/* write (2,1) */ +/* write (2,1) or (1,2) */ +/* read (1,0) and (1,3) and then write (2,2) or (1,1) */ +/* no reads or writes on VOIBUF */ +/* Finally, read (HALF,3) */ +/* Internal: */ +/* QS - Ratio of preemphasized to full-band energies */ +/* RC1 - First reflection coefficient */ +/* AR_B - Product of the causal forward and reverse pitch prediction gain +s*/ +/* AR_F - Product of the noncausal forward and rev. pitch prediction gain +s*/ +/* ZC - Zero crossing rate */ +/* DITHER - Zero crossing threshold level */ +/* MAXMIN - AMDF's 1 octave windowed maximum-to-minimum ratio */ +/* MINPTR - Location of minimum AMDF value */ +/* NVDC - Number of elements in each VDC vector */ +/* NVDCL - Number of VDC vectors */ +/* VDCL - SNR values corresponding to the set of VDC's */ +/* VDC - 2-D voicing decision coefficient vector */ +/* VALUE(9) - Voicing Parameters */ +/* VOICE(2,3)- History of LDA results */ +/* On every call when (HALF .EQ. 1), VOICE(*,I+1) is */ +/* shifted back to VOICE(*,I), for I=1,2. */ +/* VOICE(HALF,3) is written on every call. */ +/* Depending on several conditions, one or more of */ +/* (1,1), (1,2), (2,1), and (2,2) might then be read. */ +/* LBE - Ratio of low-band instantaneous to average energies */ +/* FBE - Ratio of full-band instantaneous to average energies */ +/* LBVE - Low band voiced energy */ +/* LBUE - Low band unvoiced energy */ +/* FBVE - Full band voiced energy */ +/* FBUE - Full band unvoiced energy */ +/* OFBUE - Previous full-band unvoiced energy */ +/* OLBUE - Previous low-band unvoiced energy */ +/* REF - Reference energy for initialization and DITHER threshold */ +/* SNR - Estimate of signal-to-noise ratio */ +/* SNR2 - Estimate of low-band signal-to-noise ratio */ +/* SNRL - SNR level number */ +/* OT - Onset transition present */ +/* VSTATE - Decimal interpretation of binary voicing classifications */ +/* FIRST - First call flag */ + +/* This subroutine maintains local state from one call to the next. If */ +/* you want to switch to using a new audio stream for this filter, or */ +/* reinitialize its state for any other reason, call the ENTRY */ +/* INITVOICIN. */ + +/* Subroutine */ int voicin_(integer *vwin, real *inbuf, real * + lpbuf, integer *buflim, integer *half, real *minamd, real *maxamd, + integer *mintau, real *ivrc, integer *obound, integer *voibuf, + integer *af, struct lpc10_encoder_state *st) +{ + /* Initialized data */ + + real *dither; + static real vdc[100] /* was [10][10] */ = { 0.f,1714.f,-110.f, + 334.f,-4096.f,-654.f,3752.f,3769.f,0.f,1181.f,0.f,874.f,-97.f, + 300.f,-4096.f,-1021.f,2451.f,2527.f,0.f,-500.f,0.f,510.f,-70.f, + 250.f,-4096.f,-1270.f,2194.f,2491.f,0.f,-1500.f,0.f,500.f,-10.f, + 200.f,-4096.f,-1300.f,2e3f,2e3f,0.f,-2e3f,0.f,500.f,0.f,0.f, + -4096.f,-1300.f,2e3f,2e3f,0.f,-2500.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f, + 0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f, + 0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f, + 0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f }; + static integer nvdcl = 5; + static real vdcl[10] = { 600.f,450.f,300.f,200.f,0.f,0.f,0.f,0.f,0.f,0.f } + ; + + /* System generated locals */ + integer inbuf_offset = 0, lpbuf_offset = 0, i__1, i__2; + real r__1, r__2; + + /* Builtin functions */ + integer i_nint(real *); + double sqrt(doublereal); + + /* Local variables */ + real ar_b__, ar_f__; + integer *lbve, *lbue, *fbve, *fbue; + integer snrl, i__; + integer *ofbue, *sfbue; + real *voice; + integer *olbue, *slbue; + real value[9]; + integer zc; + logical ot; + real qs; + real *maxmin; + integer vstate; + real rc1; + extern /* Subroutine */ int vparms_(integer *, real *, real *, integer *, + integer *, real *, integer *, integer *, integer *, integer *, + real *, real *, real *, real *); + integer fbe, lbe; + real *snr; + real snr2; + +/* Global Variables: */ +/* Arguments */ +/* $Log$ + * Revision 1.16 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.15 2003/11/23 22:14:32 markster +/* Various warning cleanups +/* +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:40 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.2 1996/08/20 20:45:00 jaf + * Removed all static local variables that were SAVE'd in the Fortran + * code, and put them in struct lpc10_encoder_state that is passed as an + * argument. + * + * Removed init function, since all initialization is now done in + * init_lpc10_encoder_state(). + * + * Revision 1.1 1996/08/19 22:30:14 jaf + * Initial revision + * */ +/* Revision 1.3 1996/03/29 22:05:55 jaf */ +/* Commented out the common block variables that are not needed by the */ +/* embedded version. */ + +/* Revision 1.2 1996/03/26 19:34:50 jaf */ +/* Added comments indicating which constants are not needed in an */ +/* application that uses the LPC-10 coder. */ + +/* Revision 1.1 1996/02/07 14:44:09 jaf */ +/* Initial revision */ + +/* LPC Processing control variables: */ + +/* *** Read-only: initialized in setup */ + +/* Files for Speech, Parameter, and Bitstream Input & Output, */ +/* and message and debug outputs. */ + +/* Here are the only files which use these variables: */ + +/* lpcsim.f setup.f trans.f error.f vqsetup.f */ + +/* Many files which use fdebug are not listed, since it is only used in */ +/* those other files conditionally, to print trace statements. */ +/* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* LPC order, Frame size, Quantization rate, Bits per frame, */ +/* Error correction */ +/* Subroutine SETUP is the only place where order is assigned a value, */ +/* and that value is 10. It could increase efficiency 1% or so to */ +/* declare order as a constant (i.e., a Fortran PARAMETER) instead of as +*/ +/* a variable in a COMMON block, since it is used in many places in the */ +/* core of the coding and decoding routines. Actually, I take that back. +*/ +/* At least when compiling with f2c, the upper bound of DO loops is */ +/* stored in a local variable before the DO loop begins, and then that is +*/ +/* compared against on each iteration. */ +/* Similarly for lframe, which is given a value of MAXFRM in SETUP. */ +/* Similarly for quant, which is given a value of 2400 in SETUP. quant */ +/* is used in only a few places, and never in the core coding and */ +/* decoding routines, so it could be eliminated entirely. */ +/* nbits is similar to quant, and is given a value of 54 in SETUP. */ +/* corrp is given a value of .TRUE. in SETUP, and is only used in the */ +/* subroutines ENCODE and DECODE. It doesn't affect the speed of the */ +/* coder significantly whether it is .TRUE. or .FALSE., or whether it is +*/ +/* a constant or a variable, since it is only examined once per frame. */ +/* Leaving it as a variable that is set to .TRUE. seems like a good */ +/* idea, since it does enable some error-correction capability for */ +/* unvoiced frames, with no change in the coding rate, and no noticeable +*/ +/* quality difference in the decoded speech. */ +/* integer quant, nbits */ +/* *** Read/write: variables for debugging, not needed for LPC algorithm +*/ + +/* Current frame, Unstable frames, Output clip count, Max onset buffer, +*/ +/* Debug listing detail level, Line count on listing page */ + +/* nframe is not needed for an embedded LPC10 at all. */ +/* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */ +/* ERROR, which is only called from RCCHK. When LPC10 is embedded into */ +/* an application, I would recommend removing the call to ERROR in RCCHK, +*/ +/* and remove ERROR and nunsfm completely. */ +/* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in +*/ +/* sread.f. When LPC10 is embedded into an application, one might want */ +/* to cause it to be incremented in a routine that takes the output of */ +/* SYNTHS and sends it to an audio device. It could be optionally */ +/* displayed, for those that might want to know what it is. */ +/* maxosp is never initialized to 0 in SETUP, although it probably should +*/ +/* be, and it is updated in subroutine ANALYS. I doubt that its value */ +/* would be of much interest to an application in which LPC10 is */ +/* embedded. */ +/* listl and lincnt are not needed for an embedded LPC10 at all. */ +/* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */ +/* common /contrl/ quant, nbits */ +/* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */ +/* Parameters/constants */ +/* Voicing coefficient and Linear Discriminant Analysis variables: +*/ +/* Max number of VDC's and VDC levels */ +/* The following are not Fortran PARAMETER's, but they are */ +/* initialized with DATA statements, and never modified. */ +/* Actual number of VDC's and levels */ +/* Local variables that need not be saved */ +/* Note: */ + +/* VALUE(1) through VALUE(8) are assigned values, but VALUE(9) */ +/* never is. Yet VALUE(9) is read in the loop that begins "DO I = +*/ +/* 1, 9" below. I believe that this doesn't cause any problems in +*/ +/* this subroutine, because all VDC(9,*) array elements are 0, and +*/ +/* this is what is multiplied by VALUE(9) in all cases. Still, it +*/ +/* would save a multiplication to change the loop to "DO I = 1, 8". +*/ +/* Local state */ +/* WARNING! */ + +/* VOICE, SFBUE, and SLBUE should be saved from one invocation to */ +/* the next, but they are never given an initial value. */ + +/* Does Fortran 77 specify some default initial value, like 0, or */ +/* is it undefined? If it is undefined, then this code should be */ +/* corrected to specify an initial value. */ + +/* For VOICE, note that it is "shifted" in the statement that */ +/* begins "IF (HALF .EQ. 1) THEN" below. Also, uninitialized */ +/* values in the VOICE array can only affect entries in the VOIBUF +*/ +/* array that are for the same frame, or for an older frame. Thus +*/ +/* the effects of uninitialized values in VOICE cannot linger on */ +/* for more than 2 or 3 frame times. */ + +/* For SFBUE and SLBUE, the effects of uninitialized values can */ +/* linger on for many frame times, because their previous values */ +/* are exponentially decayed. Thus it is more important to choose +*/ +/* initial values for these variables. I would guess that a */ +/* reasonable initial value for SFBUE is REF/16, the same as used */ +/* for FBUE and OFBUE. Similarly, SLBUE can be initialized to */ +/* REF/32, the same as for LBUE and OLBUE. */ + +/* These guessed initial values should be validated by re-running */ +/* the modified program on some audio samples. */ + +/* Declare and initialize filters: */ + + dither = (&st->dither); + snr = (&st->snr); + maxmin = (&st->maxmin); + voice = (&st->voice[0]); + lbve = (&st->lbve); + lbue = (&st->lbue); + fbve = (&st->fbve); + fbue = (&st->fbue); + ofbue = (&st->ofbue); + olbue = (&st->olbue); + sfbue = (&st->sfbue); + slbue = (&st->slbue); + + /* Parameter adjustments */ + if (vwin) { + --vwin; + } + if (buflim) { + --buflim; + } + if (inbuf) { + inbuf_offset = buflim[1]; + inbuf -= inbuf_offset; + } + if (lpbuf) { + lpbuf_offset = buflim[3]; + lpbuf -= lpbuf_offset; + } + if (ivrc) { + --ivrc; + } + if (obound) { + --obound; + } + if (voibuf) { + --voibuf; + } + + /* Function Body */ + +/* The following variables are saved from one invocation to the */ +/* next, but are not initialized with DATA statements. This is */ +/* acceptable, because FIRST is initialized ot .TRUE., and the */ +/* first time that this subroutine is then called, they are all */ +/* given initial values. */ + +/* SNR */ +/* LBVE, LBUE, FBVE, FBUE, OFBUE, OLBUE */ + +/* MAXMIN is initialized on the first call, assuming that HALF */ +/* .EQ. 1 on first call. This is how ANALYS calls this subroutine. +*/ + +/* Voicing Decision Parameter vector (* denotes zero coefficient): */ + +/* * MAXMIN */ +/* LBE/LBVE */ +/* ZC */ +/* RC1 */ +/* QS */ +/* IVRC2 */ +/* aR_B */ +/* aR_F */ +/* * LOG(LBE/LBVE) */ +/* Define 2-D voicing decision coefficient vector according to the voicin +g*/ +/* parameter order above. Each row (VDC vector) is optimized for a speci +fic*/ +/* SNR. The last element of the vector is the constant. */ +/* E ZC RC1 Qs IVRC2 aRb aRf c */ + +/* The VOICE array contains the result of the linear discriminant functio +n*/ +/* (analog values). The VOIBUF array contains the hard-limited binary +*/ +/* voicing decisions. The VOICE and VOIBUF arrays, according to FORTRAN + */ +/* memory allocation, are addressed as: */ + +/* (half-frame number, future-frame number) */ + +/* | Past | Present | Future1 | Future2 | */ +/* | 1,0 | 2,0 | 1,1 | 2,1 | 1,2 | 2,2 | 1,3 | 2,3 | ---> time */ + +/* Update linear discriminant function history each frame: */ + if (*half == 1) { + voice[0] = voice[2]; + voice[1] = voice[3]; + voice[2] = voice[4]; + voice[3] = voice[5]; + *maxmin = *maxamd / max(*minamd,1.f); + } +/* Calculate voicing parameters twice per frame: */ + vparms_(&vwin[1], &inbuf[inbuf_offset], &lpbuf[lpbuf_offset], &buflim[1], + half, dither, mintau, &zc, &lbe, &fbe, &qs, &rc1, &ar_b__, & + ar_f__); +/* Estimate signal-to-noise ratio to select the appropriate VDC vector. +*/ +/* The SNR is estimated as the running average of the ratio of the */ +/* running average full-band voiced energy to the running average */ +/* full-band unvoiced energy. SNR filter has gain of 63. */ + r__1 = (*snr + *fbve / (real) max(*fbue,1)) * 63 / 64.f; + *snr = (real) i_nint(&r__1); + snr2 = *snr * *fbue / max(*lbue,1); +/* Quantize SNR to SNRL according to VDCL thresholds. */ + snrl = 1; + i__1 = nvdcl - 1; + for (snrl = 1; snrl <= i__1; ++snrl) { + if (snr2 > vdcl[snrl - 1]) { + goto L69; + } + } +/* (Note: SNRL = NVDCL here) */ +L69: +/* Linear discriminant voicing parameters: */ + value[0] = *maxmin; + value[1] = (real) lbe / max(*lbve,1); + value[2] = (real) zc; + value[3] = rc1; + value[4] = qs; + value[5] = ivrc[2]; + value[6] = ar_b__; + value[7] = ar_f__; +/* Evaluation of linear discriminant function: */ + voice[*half + 3] = vdc[snrl * 10 - 1]; + for (i__ = 1; i__ <= 8; ++i__) { + voice[*half + 3] += vdc[i__ + snrl * 10 - 11] * value[i__ - 1]; + } +/* Classify as voiced if discriminant > 0, otherwise unvoiced */ +/* Voicing decision for current half-frame: 1 = Voiced; 0 = Unvoiced */ + if (voice[*half + 3] > 0.f) { + voibuf[*half + 6] = 1; + } else { + voibuf[*half + 6] = 0; + } +/* Skip voicing decision smoothing in first half-frame: */ +/* Give a value to VSTATE, so that trace statements below will print +*/ +/* a consistent value from one call to the next when HALF .EQ. 1. */ +/* The value of VSTATE is not used for any other purpose when this is +*/ +/* true. */ + vstate = -1; + if (*half == 1) { + goto L99; + } +/* Voicing decision smoothing rules (override of linear combination): */ + +/* Unvoiced half-frames: At least two in a row. */ +/* -------------------- */ + +/* Voiced half-frames: At least two in a row in one frame. */ +/* ------------------- Otherwise at least three in a row. */ +/* (Due to the way transition frames are encoded) */ + +/* In many cases, the discriminant function determines how to smooth. */ +/* In the following chart, the decisions marked with a * may be overridden +.*/ + +/* Voicing override of transitions at onsets: */ +/* If a V/UV or UV/V voicing decision transition occurs within one-half +*/ +/* frame of an onset bounding a voicing window, then the transition is */ +/* moved to occur at the onset. */ + +/* P 1F */ +/* ----- ----- */ +/* 0 0 0 0 */ +/* 0 0 0* 1 (If there is an onset there) */ +/* 0 0 1* 0* (Based on 2F and discriminant distance) */ +/* 0 0 1 1 */ +/* 0 1* 0 0 (Always) */ +/* 0 1* 0* 1 (Based on discriminant distance) */ +/* 0* 1 1 0* (Based on past, 2F, and discriminant distance) */ +/* 0 1* 1 1 (If there is an onset there) */ +/* 1 0* 0 0 (If there is an onset there) */ +/* 1 0 0 1 */ +/* 1 0* 1* 0 (Based on discriminant distance) */ +/* 1 0* 1 1 (Always) */ +/* 1 1 0 0 */ +/* 1 1 0* 1* (Based on 2F and discriminant distance) */ +/* 1 1 1* 0 (If there is an onset there) */ +/* 1 1 1 1 */ + +/* Determine if there is an onset transition between P and 1F. */ +/* OT (Onset Transition) is true if there is an onset between */ +/* P and 1F but not after 1F. */ + ot = ((obound[1] & 2) != 0 || obound[2] == 1) && (obound[3] & 1) == 0; +/* Multi-way dispatch on voicing decision history: */ + vstate = (voibuf[3] << 3) + (voibuf[4] << 2) + (voibuf[5] << 1) + voibuf[ + 6]; + switch (vstate + 1) { + case 1: goto L99; + case 2: goto L1; + case 3: goto L2; + case 4: goto L99; + case 5: goto L4; + case 6: goto L5; + case 7: goto L6; + case 8: goto L7; + case 9: goto L8; + case 10: goto L99; + case 11: goto L10; + case 12: goto L11; + case 13: goto L99; + case 14: goto L13; + case 15: goto L14; + case 16: goto L99; + } +L1: + if (ot && voibuf[7] == 1) { + voibuf[5] = 1; + } + goto L99; +L2: + if (voibuf[7] == 0 || voice[2] < -voice[3]) { + voibuf[5] = 0; + } else { + voibuf[6] = 1; + } + goto L99; +L4: + voibuf[4] = 0; + goto L99; +L5: + if (voice[1] < -voice[2]) { + voibuf[4] = 0; + } else { + voibuf[5] = 1; + } + goto L99; +/* VOIBUF(2,0) must be 0 */ +L6: + if (voibuf[1] == 1 || voibuf[7] == 1 || voice[3] > voice[0]) { + voibuf[6] = 1; + } else { + voibuf[3] = 1; + } + goto L99; +L7: + if (ot) { + voibuf[4] = 0; + } + goto L99; +L8: + if (ot) { + voibuf[4] = 1; + } + goto L99; +L10: + if (voice[2] < -voice[1]) { + voibuf[5] = 0; + } else { + voibuf[4] = 1; + } + goto L99; +L11: + voibuf[4] = 1; + goto L99; +L13: + if (voibuf[7] == 0 && voice[3] < -voice[2]) { + voibuf[6] = 0; + } else { + voibuf[5] = 1; + } + goto L99; +L14: + if (ot && voibuf[7] == 0) { + voibuf[5] = 0; + } +/* GOTO 99 */ +L99: +/* Now update parameters: */ +/* ---------------------- */ + +/* During unvoiced half-frames, update the low band and full band unvoice +d*/ +/* energy estimates (LBUE and FBUE) and also the zero crossing */ +/* threshold (DITHER). (The input to the unvoiced energy filters is */ +/* restricted to be less than 10dB above the previous inputs of the */ +/* filters.) */ +/* During voiced half-frames, update the low-pass (LBVE) and all-pass */ +/* (FBVE) voiced energy estimates. */ + if (voibuf[*half + 6] == 0) { +/* Computing MIN */ + i__1 = fbe, i__2 = *ofbue * 3; + r__1 = (*sfbue * 63 + (min(i__1,i__2) << 3)) / 64.f; + *sfbue = i_nint(&r__1); + *fbue = *sfbue / 8; + *ofbue = fbe; +/* Computing MIN */ + i__1 = lbe, i__2 = *olbue * 3; + r__1 = (*slbue * 63 + (min(i__1,i__2) << 3)) / 64.f; + *slbue = i_nint(&r__1); + *lbue = *slbue / 8; + *olbue = lbe; + } else { + r__1 = (*lbve * 63 + lbe) / 64.f; + *lbve = i_nint(&r__1); + r__1 = (*fbve * 63 + fbe) / 64.f; + *fbve = i_nint(&r__1); + } +/* Set dither threshold to yield proper zero crossing rates in the */ +/* presence of low frequency noise and low level signal input. */ +/* NOTE: The divisor is a function of REF, the expected energies. */ +/* Computing MIN */ +/* Computing MAX */ + r__2 = sqrt((real) (*lbue * *lbve)) * 64 / 3000; + r__1 = max(r__2,1.f); + *dither = min(r__1,20.f); +/* Voicing decisions are returned in VOIBUF. */ + return 0; +} /* voicin_ */ diff --git a/libs/codec/lpc10/vparms.c b/libs/codec/lpc10/vparms.c new file mode 100644 index 0000000000..e40cbfd642 --- /dev/null +++ b/libs/codec/lpc10/vparms.c @@ -0,0 +1,255 @@ +/* + +$Log$ +Revision 1.15 2004/06/26 03:50:14 markster +Merge source cleanups (bug #1911) + +Revision 1.14 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.1.1.1 2003/02/12 13:59:15 matteo +mer feb 12 14:56:57 CET 2003 + +Revision 1.2 2000/01/05 08:20:40 markster +Some OSS fixes and a few lpc changes to make it actually work + + * Revision 1.1 1996/08/19 22:30:04 jaf + * Initial revision + * + +*/ + +/* -- translated by f2c (version 19951025). + You must link the resulting object file with the libraries: + -lf2c -lm (in that order) +*/ + +#include "f2c.h" + +#ifdef P_R_O_T_O_T_Y_P_E_S +extern int vparms_(integer *vwin, real *inbuf, real *lpbuf, integer *buflim, integer *half, real *dither, integer *mintau, integer *zc, integer *lbe, integer *fbe, real *qs, real *rc1, real *ar_b__, real *ar_f__); +#endif + +/* Table of constant values */ + +static real c_b2 = 1.f; + +/* ********************************************************************* */ + +/* VPARMS Version 50 */ + +/* $Log$ + * Revision 1.15 2004/06/26 03:50:14 markster + * Merge source cleanups (bug #1911) + * +/* Revision 1.14 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.1.1.1 2003/02/12 13:59:15 matteo +/* mer feb 12 14:56:57 CET 2003 +/* +/* Revision 1.2 2000/01/05 08:20:40 markster +/* Some OSS fixes and a few lpc changes to make it actually work +/* + * Revision 1.1 1996/08/19 22:30:04 jaf + * Initial revision + * */ +/* Revision 1.6 1996/03/29 18:01:16 jaf */ +/* Added some more comments about the range of INBUF and LPBUF that can */ +/* be read. Note that it is possible for index VWIN(2)+1 to be read from */ +/* INBUF, which might be outside of its defined range, although that will */ +/* require more careful checking. */ + +/* Revision 1.5 1996/03/19 00:02:02 jaf */ +/* I just noticed that the argument DITHER is modified inside of this */ +/* subroutine. Comments were added explaining the possible final values. */ + +/* Revision 1.4 1996/03/18 22:22:59 jaf */ +/* Finishing the job I said I did with the last check-in comments. */ + +/* Revision 1.3 1996/03/18 22:22:17 jaf */ +/* Just added a few comments about which array indices of the arguments */ +/* are used, and mentioning that this subroutine has no local state. */ + +/* Revision 1.2 1996/03/13 15:02:58 jaf */ +/* Comments added explaining that none of the local variables of this */ +/* subroutine need to be saved from one invocation to the next. */ + +/* Revision 1.1 1996/02/07 14:50:42 jaf */ +/* Initial revision */ + + +/* ********************************************************************* */ + +/* Calculate voicing parameters: */ + +/* Input: */ +/* VWIN - Voicing window limits */ +/* Indices 1 through 2 read. */ +/* INBUF - Input speech buffer */ +/* Indices START-1 through STOP read, */ +/* where START and STOP are defined in the code (only written once). +*/ +/* Note that STOP can be as large as VWIN(2)+1 ! */ +/* LPBUF - Low pass filtered speech */ +/* Indices START-MINTAU through STOP+MINTAU read, */ +/* where START and STOP are defined in the code (only written once). +*/ +/* BUFLIM - Array bounds for INBUF and LPBUF */ +/* Indices 1 through 4 read. */ +/* HALF - Half frame (1 or 2) */ +/* MINTAU - Lag corresponding to minimum AMDF value (pitch estimate) */ +/* Input/Output: */ +/* DITHER - Zero crossing threshold */ +/* The resulting value might be the negation of the input */ +/* value. It might always be the same as the input value, */ +/* if the DO loop below always executes an even number of times. */ +/* Output: (all of them are written on every call) */ +/* ZC - Zero crossing rate */ +/* LBE - Low band energy (sum of magnitudes - SM) */ +/* FBE - Full band energy (SM) */ +/* QS - Ratio of 6 dB/oct preemphasized energy to full band energy */ +/* RC1 - First reflection coefficient */ +/* AR_B - Product of the causal forward and reverse pitch */ +/* prediction gains */ +/* AR_F - Product of the noncausal forward and reverse pitch */ +/* prediction gains */ +/* Internal: */ +/* OLDSGN - Previous sign of dithered signal */ +/* VLEN - Length of voicing window */ +/* START - Lower address of current half of voicing window */ +/* STOP - Upper address of current half of voicing window */ +/* E_0 - Energy of LPF speech (sum of squares - SS) */ +/* E_B - Energy of LPF speech backward one pitch period (SS) */ +/* E_F - Energy of LPF speech forward one pitch period (SS) */ +/* R_B - Autocovariance of LPF speech backward one pitch period */ +/* R_F - Autocovariance of LPF speech forward one pitch period */ +/* LP_RMS - Energy of LPF speech (sum of magnitudes - SM) */ +/* AP_RMS - Energy of all-pass speech (SM) */ +/* E_PRE - Energy of 6dB preemphasized speech (SM) */ +/* E0AP - Energy of all-pass speech (SS) */ + +/* This subroutine has no local state. */ + +/* Subroutine */ int vparms_(integer *vwin, real *inbuf, real *lpbuf, integer + *buflim, integer *half, real *dither, integer *mintau, integer *zc, + integer *lbe, integer *fbe, real *qs, real *rc1, real *ar_b__, real * + ar_f__) +{ + /* System generated locals */ + integer inbuf_offset, lpbuf_offset, i__1; + real r__1, r__2; + + /* Builtin functions */ + double r_sign(real *, real *); + integer i_nint(real *); + + /* Local variables */ + integer vlen, stop, i__; + real e_pre__; + integer start; + real ap_rms__, e_0__, oldsgn, lp_rms__, e_b__, e_f__, r_b__, r_f__, e0ap; + +/* Arguments */ +/* Local variables that need not be saved */ +/* Calculate zero crossings (ZC) and several energy and correlation */ +/* measures on low band and full band speech. Each measure is taken */ +/* over either the first or the second half of the voicing window, */ +/* depending on the variable HALF. */ + /* Parameter adjustments */ + --vwin; + --buflim; + lpbuf_offset = buflim[3]; + lpbuf -= lpbuf_offset; + inbuf_offset = buflim[1]; + inbuf -= inbuf_offset; + + /* Function Body */ + lp_rms__ = 0.f; + ap_rms__ = 0.f; + e_pre__ = 0.f; + e0ap = 0.f; + *rc1 = 0.f; + e_0__ = 0.f; + e_b__ = 0.f; + e_f__ = 0.f; + r_f__ = 0.f; + r_b__ = 0.f; + *zc = 0; + vlen = vwin[2] - vwin[1] + 1; + start = vwin[1] + (*half - 1) * vlen / 2 + 1; + stop = start + vlen / 2 - 1; + +/* I'll use the symbol HVL in the table below to represent the value */ +/* VLEN/2. Note that if VLEN is odd, then HVL should be rounded down, */ +/* i.e., HVL = (VLEN-1)/2. */ + +/* HALF START STOP */ + +/* 1 VWIN(1)+1 VWIN(1)+HVL */ +/* 2 VWIN(1)+HVL+1 VWIN(1)+2*HVL */ + +/* Note that if VLEN is even and HALF is 2, then STOP will be */ +/* VWIN(1)+VLEN = VWIN(2)+1. That could be bad, if that index of INBUF */ +/* is undefined. */ + + r__1 = inbuf[start - 1] - *dither; + oldsgn = r_sign(&c_b2, &r__1); + i__1 = stop; + for (i__ = start; i__ <= i__1; ++i__) { + lp_rms__ += (r__1 = lpbuf[i__], abs(r__1)); + ap_rms__ += (r__1 = inbuf[i__], abs(r__1)); + e_pre__ += (r__1 = inbuf[i__] - inbuf[i__ - 1], abs(r__1)); +/* Computing 2nd power */ + r__1 = inbuf[i__]; + e0ap += r__1 * r__1; + *rc1 += inbuf[i__] * inbuf[i__ - 1]; +/* Computing 2nd power */ + r__1 = lpbuf[i__]; + e_0__ += r__1 * r__1; +/* Computing 2nd power */ + r__1 = lpbuf[i__ - *mintau]; + e_b__ += r__1 * r__1; +/* Computing 2nd power */ + r__1 = lpbuf[i__ + *mintau]; + e_f__ += r__1 * r__1; + r_f__ += lpbuf[i__] * lpbuf[i__ + *mintau]; + r_b__ += lpbuf[i__] * lpbuf[i__ - *mintau]; + r__1 = inbuf[i__] + *dither; + if (r_sign(&c_b2, &r__1) != oldsgn) { + ++(*zc); + oldsgn = -oldsgn; + } + *dither = -(*dither); + } +/* Normalized short-term autocovariance coefficient at unit sample delay + */ + *rc1 /= max(e0ap,1.f); +/* Ratio of the energy of the first difference signal (6 dB/oct preemphas +is)*/ +/* to the energy of the full band signal */ +/* Computing MAX */ + r__1 = ap_rms__ * 2.f; + *qs = e_pre__ / max(r__1,1.f); +/* aR_b is the product of the forward and reverse prediction gains, */ +/* looking backward in time (the causal case). */ + *ar_b__ = r_b__ / max(e_b__,1.f) * (r_b__ / max(e_0__,1.f)); +/* aR_f is the same as aR_b, but looking forward in time (non causal case +).*/ + *ar_f__ = r_f__ / max(e_f__,1.f) * (r_f__ / max(e_0__,1.f)); +/* Normalize ZC, LBE, and FBE to old fixed window length of 180. */ +/* (The fraction 90/VLEN has a range of .58 to 1) */ + r__2 = (real) (*zc << 1); + r__1 = r__2 * (90.f / vlen); + *zc = i_nint(&r__1); +/* Computing MIN */ + r__1 = lp_rms__ / 4 * (90.f / vlen); + i__1 = i_nint(&r__1); + *lbe = min(i__1,32767); +/* Computing MIN */ + r__1 = ap_rms__ / 4 * (90.f / vlen); + i__1 = i_nint(&r__1); + *fbe = min(i__1,32767); + return 0; +} /* vparms_ */ +