Compare commits

...

68 Commits
0.1.1 ... 0.1.3

Author SHA1 Message Date
Kevin P. Fleming
836e861dde remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.1.3@7221 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 18:24:39 +00:00
Kevin P. Fleming
04ec7f1429 automatic tag renames
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.1.3@7201 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-27 17:18:34 +00:00
Admin Commit
35e505b579 This commit was manufactured by cvs2svn to create tag 'v0-1-3'.
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/v0-1-3@210 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-05-02 19:18:58 +00:00
Mark Spencer
e69da9d0ab Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@209 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-05-02 19:18:58 +00:00
Mark Spencer
426381275d Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@208 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-04-06 16:17:14 +00:00
Mark Spencer
5e0525cc65 Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@207 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-03-26 01:59:06 +00:00
Mark Spencer
c44f9f168a Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@206 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-24 07:14:18 +00:00
Mark Spencer
ec6fdc8c2b Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@205 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-23 01:06:34 +00:00
Mark Spencer
101435bd3d Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@204 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-13 04:27:32 +00:00
Mark Spencer
255ccb33d5 Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@203 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-10 17:43:38 +00:00
Mark Spencer
6ada28a442 Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@202 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-09 23:17:36 +00:00
Mark Spencer
0c3b134da5 Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@201 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-09 19:58:18 +00:00
Mark Spencer
aa6a80f31d Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-07 11:02:42 +00:00
Mark Spencer
5800db6556 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@198 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-07 10:54:40 +00:00
Mark Spencer
9440db13f4 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@197 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-06 13:24:57 +00:00
Mark Spencer
c8640d5486 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@196 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-06 12:33:15 +00:00
Mark Spencer
22e0c573b6 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@195 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-06 11:55:52 +00:00
Mark Spencer
9fafdf3ccc Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@194 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-06 11:50:20 +00:00
Mark Spencer
cec9e6563d Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@193 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-06 10:19:32 +00:00
Mark Spencer
cb625a6d3c Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@192 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 20:03:55 +00:00
Mark Spencer
2ebdf66e5f Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@191 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 17:22:42 +00:00
Mark Spencer
c340c2093c Version 0.3.0 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:40 +00:00
Mark Spencer
7b826e7687 Version 0.1.7 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@189 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:39 +00:00
Mark Spencer
1cc89abf56 Version 0.2.0 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@188 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:39 +00:00
Mark Spencer
f629f87836 Version 0.1.6 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@187 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:38 +00:00
Mark Spencer
e001c19bec Version 0.1.12 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:38 +00:00
Mark Spencer
f60ff8db65 Version 0.1.11 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@185 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:37 +00:00
Mark Spencer
33dbe25ff9 Version 0.1.5 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@184 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:37 +00:00
Mark Spencer
e077f63d6a Version 0.1.10 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@183 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:36 +00:00
Mark Spencer
b0d73ea947 Version 0.1.11 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@182 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:36 +00:00
Mark Spencer
7a355cb6e5 Version 0.1.4 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@181 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:36 +00:00
Mark Spencer
7e68a64751 Version 0.1.10 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@180 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:35 +00:00
Mark Spencer
0482ce4dcb Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@179 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:35 +00:00
Mark Spencer
1b0c5f3ac4 Version 0.1.9 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@178 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:35 +00:00
Mark Spencer
3b82506dd3 Version 0.1.8 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@177 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:34 +00:00
Mark Spencer
98511b9093 Version 0.1.8 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@176 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:33 +00:00
Mark Spencer
3fe1fe6462 Version 0.1.7 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@175 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:33 +00:00
Mark Spencer
17337b33ba Version 0.1.6 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@174 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:32 +00:00
Mark Spencer
ab7d243daf Version 0.1.5 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@173 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:31 +00:00
Mark Spencer
e58a5412db Version 0.1.4 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@172 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:30 +00:00
Mark Spencer
2693f2539a Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@171 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:29 +00:00
Mark Spencer
0ac7cc0094 Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@170 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:28 +00:00
Mark Spencer
6f0ba39ae5 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@169 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 08:20:27 +00:00
Mark Spencer
41567d7c5e Version 0.3.0 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@168 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:20:06 +00:00
Mark Spencer
2fd4e9d6b6 Version 0.2.0 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@167 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:20:05 +00:00
Mark Spencer
93804c6d8b Version 0.1.12 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@166 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:20:04 +00:00
Mark Spencer
cf1911bde0 Version 0.1.11 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@165 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:20:03 +00:00
Mark Spencer
1541d05cc4 Version 0.1.10 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@164 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:20:02 +00:00
Mark Spencer
dcd35351a3 Version 0.1.9 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@163 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:20:01 +00:00
Mark Spencer
50eec3f607 Version 0.1.8 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@162 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:20:00 +00:00
Mark Spencer
1a3c6a8937 Version 0.1.7 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@161 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:19:59 +00:00
Mark Spencer
7c117b64c5 Version 0.1.6 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@160 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:19:58 +00:00
Mark Spencer
51db1d4c7c Version 0.1.5 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@159 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:19:57 +00:00
Mark Spencer
270d4f9660 Version 0.1.4 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:19:56 +00:00
Mark Spencer
d063d333b6 Version 0.1.3 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@157 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:19:55 +00:00
Mark Spencer
77b4e51f3c Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@156 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-05 00:19:54 +00:00
Mark Spencer
a844f1e904 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@155 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-04 16:24:38 +00:00
Mark Spencer
53d37127de Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@154 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-03 17:02:23 +00:00
Mark Spencer
f24e6a3d8b Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@153 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-02 23:51:30 +00:00
Mark Spencer
aa07102df2 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@152 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2000-01-02 20:59:00 +00:00
Mark Spencer
5099c2edf7 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@151 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1999-12-27 20:49:06 +00:00
Mark Spencer
d5e6ab1569 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@150 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1999-12-27 19:20:20 +00:00
Mark Spencer
e2aa31c8ce Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@149 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1999-12-25 22:31:01 +00:00
Mark Spencer
a261bdc235 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@148 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1999-12-25 00:46:58 +00:00
Mark Spencer
388961dc35 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@147 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1999-12-25 00:13:34 +00:00
Mark Spencer
24e967b70a Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@146 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1999-12-23 19:34:00 +00:00
Mark Spencer
3eede21279 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@145 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1999-12-23 00:17:22 +00:00
Mark Spencer
a43ac415e6 Version 0.1.2 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@144 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1999-12-22 23:07:49 +00:00
264 changed files with 15194 additions and 619 deletions

0
BUGS Executable file → Normal file
View File

24
CHANGES Executable file → Normal file
View File

@@ -1,3 +1,27 @@
* Asterisk 0.1.3
-- Update VoFR for latest sangoma code
-- Update QuickNet Driver
-- Add text message handling
-- Fix transfers to use "default" if not in current context
-- Add call parking
-- Improve format/content negotiation
-- Added support for multiple languages
-- Bug fixes, as always...
* Asterisk 0.1.2
-- Updated README file with a "Getting Started" section
-- Added sample sounds and configuration files.
-- Added LPC10 very low bandwidth (low quality) compression
-- Enhanced translation selection mechanism.
-- Enhanced IAX jitter buffer, improved reliability
-- Support echo cancelation on PhoneJack
-- Updated PhoneJack driver to std. Telephony interface
-- Added app_echo for evaluating VoIP latency
-- Added app_system to execute arbitrary programs
-- Updated sample configuration files
-- Added OSS channel driver (full duplex only)
-- Added IAX implementation
-- Fixed some deadlocks.
-- A whole bunch of bug fixes
* Asterisk 0.1.1
-- Revised translator, fixed some general race conditions throughout *
-- Made dialer somewhat more aware of incompatible voice channels

0
CREDITS Executable file → Normal file
View File

0
LICENSE Executable file → Normal file
View File

66
Makefile Executable file → Normal file
View File

@@ -16,16 +16,32 @@
MODULES_DIR=/usr/lib/asterisk/modules
# Pentium Pro Optimize
#PROC=i686
# Pentium Optimize
PROC=i586
DEBUG=-g #-pg
INCLUDE=-Iinclude -I../include
CFLAGS=-pipe -Wall -Werror -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT
CFLAGS+=$(shell if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686"; fi)
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
CFLAGS+=$(shell [ ! -f /usr/include/linux/if_wanpipe.h ] && echo " -DOLD_SANGOMA_API")
SUBDIRS=channels pbx apps codecs formats
LIBS=-ldl -lpthread -lreadline # -lefence
OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o translate.o file.o say.o pbx.o cli.o asterisk.o
LIBS=-ldl -lpthread -lreadline #-lefence
OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o translate.o file.o say.o pbx.o cli.o md5.o asterisk.o
CC=gcc
INSTALL=install
_all: all
@echo " +--------- Asterisk Build Complete ---------+"
@echo " + Asterisk has successfully been built, but +"
@echo " + cannot be run before being installed by +"
@echo " + running: +"
@echo " + +"
@echo " + make install +"
@echo " + +"
@echo " +-------------------------------------------+"
all: asterisk subdirs
asterisk: $(OBJS)
@@ -38,8 +54,52 @@ clean:
for x in $(SUBDIRS); do $(MAKE) -C $$x clean || exit 1 ; done
rm -f *.o *.so asterisk
datafiles: all
mkdir -p /var/lib/asterisk/sounds/digits
for x in sounds/digits/*; do \
install $$x /var/lib/asterisk/sounds/digits ; \
done
for x in sounds/vm-* sounds/transfer* ; do \
install $$x /var/lib/asterisk/sounds ; \
done
install: all
mkdir -p $(MODULES_DIR)
for x in $(SUBDIRS); do $(MAKE) -C $$x install || exit 1 ; done
install -d /usr/include/asterisk
install include/asterisk/*.h /usr/include/asterisk
rm -f /var/lib/asterisk/sounds/vm
mkdir -p /var/spool/asterisk/vm
rm -f /usr/lib/asterisk/modules/chan_ixj.so
mkdir -p /var/lib/asterisk/sounds
( cd /var/lib/asterisk/sounds ; ln -s ../../../spool/asterisk/vm . )
@echo " +---- Asterisk Installation Complete -------+"
@echo " + Asterisk has successfully been installed. +"
@echo " + If you would like to install the sample +"
@echo " + configuration files (overwriting any +"
@echo " + existing config files), run: +"
@echo " + +"
@echo " + make samples +"
@echo " + +"
@echo " +-------------------------------------------+"
samples: all datafiles
mkdir -p /etc/asterisk
for x in configs/*.sample; do \
if [ -f /etc/asterisk/`basename $$x .sample` ]; then \
mv -f /etc/asterisk/`basename $$x .sample` /etc/asterisk/`basename $$x .sample`.old ; \
fi ; \
install $$x /etc/asterisk/`basename $$x .sample` ;\
done
for x in sounds/demo-*; do \
install $$x /var/lib/asterisk/sounds; \
done
mkdir -p /var/spool/asterisk/vm/1234/INBOX
:> /var/lib/asterisk/sounds/vm/1234/unavail.gsm
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \
cat /var/lib/asterisk/sounds/$$x.gsm >> /var/lib/asterisk/sounds/vm/1234/unavail.gsm ; \
done
:> /var/lib/asterisk/sounds/vm/1234/busy.gsm
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isonphone; do \
cat /var/lib/asterisk/sounds/$$x.gsm >> /var/lib/asterisk/sounds/vm/1234/busy.gsm ; \
done

56
README Executable file → Normal file
View File

@@ -22,6 +22,60 @@ as well.
If you want to use format_wav module, then you need a very recent
version of libaudiofile (at least version 0.2.0, or you can apply the
following patch to version 0.1.9):
included patch. RPMS for the patched libaudiofile are available at:
ftp://ftp.asteriskpbx.com/pub/asterisk/support
* GETTING STARTED
First, be sure you've installed the required libaudiofile upgrade if
you want to use the non-GSM WAV format. Next, be sure you've got
supported hardware. To use Asterisk right now, you will need one of
the following:
* Adtran Atlas 800 Plus
* QuickNet Internet PhoneJack
* Full Duplex Sound Card supported by Linux
Assuming you have one of these (most likely the third) you're ready to
proceed:
1) Run "make"
2) Run "make install"
If this is your first time working with Asterisk, you may wish to install
the sample PBX, with demonstration extensions, etc. If so, run:
"make samples"
Doing so will overwrite any existing config files you have.
Finally, you can launch Asterisk with:
./asterisk -vvvc
If you get an error about unresolved symbols, install the updated
libaudiofile (available at ftp://ftp.asteriskpbx.com/pub/asterisk/support
You'll see a bunch of verbose messages fly by your screen as Asterisk
initializes (that's the "very very verbose" mode). When it's ready, if
you specified the "c" then you'll get a command line console, that looks
like this:
*CLI>
You can type "help" at any time to get help with the system. For help
with a specific command, type "help <command>". To start the PBX using
your sound card, you can type "dial" to dial the PBX. Then you can use
"answer", "hangup", and "dial" to simulate the actions of a telephone.
Remember that if you don't have a full duplex sound card (And asterisk
will tell you somewhere in its verbose messages if you do/don't) than it
won't work right (not yet).
Feel free to look over the configuration files in /etc/asterisk, where
you'll find a lot of information about what you can do with Asterisk.
Finally, you may wish to visit the web site and join the mailing list if
you're interested in getting more information.
Mark

2
apps/Makefile Executable file → Normal file
View File

@@ -11,7 +11,7 @@
# the GNU General Public License
#
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_intercom.so app_mp3.so
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_intercom.so app_mp3.so app_system.so app_echo.so
CFLAGS+=

294
apps/app_dial.c Executable file → Normal file
View File

@@ -18,6 +18,7 @@
#include <asterisk/options.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/say.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
@@ -25,14 +26,31 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <pthread.h>
static char *tdesc = "Trivial Dialing Application";
static char *tdesc = "Dialing/Parking Application";
static char *app = "Dial";
static char *parkedcall = "ParkedCall";
/* No more than 90 seconds parked before you do something with them */
static int parkingtime = 90000;
/* Context for which parking is made accessible */
static char parking_con[AST_MAX_EXTENSION] = "default";
/* Extension you type to park the call */
static char parking_ext[AST_MAX_EXTENSION] = "700";
/* First available extension for parking */
static int parking_start = 701;
/* Last available extension for parking */
static int parking_stop = 750;
/* We define a customer "local user" structure because we
use it not only for keeping track of what is in use but
also for keeping track of who we're dialing. */
@@ -44,8 +62,164 @@ struct localuser {
struct localuser *next;
};
struct parkeduser {
struct ast_channel *chan;
struct timeval start;
int parkingnum;
/* Where to go if our parking time expires */
char context[AST_MAX_EXTENSION];
char exten[AST_MAX_EXTENSION];
int priority;
struct parkeduser *next;
};
static struct parkeduser *parkinglot;
static pthread_mutex_t parking_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t parking_thread;
LOCAL_USER_DECL;
static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect);
static int park_call(struct ast_channel *chan, struct ast_channel *peer)
{
/* We put the user in the parking list, then wake up the parking thread to be sure it looks
after these channels too */
struct parkeduser *pu, *cur;
int x;
pu = malloc(sizeof(struct parkeduser));
if (pu) {
pthread_mutex_lock(&parking_lock);
for (x=parking_start;x<=parking_stop;x++) {
cur = parkinglot;
while(cur) {
if (cur->parkingnum == x)
break;
cur = cur->next;
}
if (!cur)
break;
}
if (x <= parking_stop) {
pu->chan = chan;
gettimeofday(&pu->start, NULL);
pu->parkingnum = x;
/* Remember what had been dialed, so that if the parking
expires, we try to come back to the same place */
strncpy(pu->context, chan->context, sizeof(pu->context));
strncpy(pu->exten, chan->exten, sizeof(pu->exten));
pu->priority = chan->priority;
pu->next = parkinglot;
parkinglot = pu;
pthread_mutex_unlock(&parking_lock);
/* Wake up the (presumably select()ing) thread */
pthread_kill(parking_thread, SIGURG);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d\n", pu->chan->name, pu->parkingnum);
ast_say_digits(peer, pu->parkingnum, peer->language);
return 0;
} else {
ast_log(LOG_WARNING, "No more parking spaces\n");
free(pu);
pthread_mutex_unlock(&parking_lock);
return -1;
}
} else {
ast_log(LOG_WARNING, "Out of memory\n");
return -1;
}
return 0;
}
static void *do_parking_thread(void *ignore)
{
int ms, tms, max;
struct parkeduser *pu, *pl, *pt = NULL;
struct timeval tv;
struct ast_frame *f;
fd_set rfds, efds;
fd_set nrfds, nefds;
FD_ZERO(&rfds);
FD_ZERO(&efds);
for (;;) {
ms = -1;
max = -1;
pthread_mutex_lock(&parking_lock);
pl = NULL;
pu = parkinglot;
gettimeofday(&tv, NULL);
FD_ZERO(&nrfds);
FD_ZERO(&nefds);
while(pu) {
tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
if (tms > parkingtime) {
/* They've been waiting too long, send them back to where they came. Theoretically they
should have their original extensions and such, but we copy to be on the safe side */
strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context));
pu->chan->priority = pu->priority;
/* Start up the PBX, or hang them up */
if (ast_pbx_start(pu->chan)) {
ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
ast_hangup(pu->chan);
}
/* And take them out of the parking lot */
if (pl)
pl->next = pu->next;
else
parkinglot = pu->next;
pt = pu;
pu = pu->next;
free(pt);
} else if (FD_ISSET(pu->chan->fd, &rfds) || FD_ISSET(pu->chan->fd, &efds)) {
/* See if they need servicing */
f = ast_read(pu->chan);
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
/* There's a problem, hang them up*/
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
ast_hangup(pu->chan);
/* And take them out of the parking lot */
if (pl)
pl->next = pu->next;
else
parkinglot = pu->next;
pt = pu;
pu = pu->next;
free(pt);
} else {
/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
ast_frfree(f);
goto std; /* XXX Ick: jumping into an else statement??? XXX */
}
} else {
/* Keep this one for next one */
std: FD_SET(pu->chan->fd, &nrfds);
FD_SET(pu->chan->fd, &nefds);
/* Keep track of our longest wait */
if ((tms < ms) || (ms < 0))
ms = tms;
if (pu->chan->fd > max)
max = pu->chan->fd;
pl = pu;
pu = pu->next;
}
}
pthread_mutex_unlock(&parking_lock);
rfds = nrfds;
efds = nefds;
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms % 1000) * 1000;
/* Wait for something to happen */
select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
pthread_testcancel();
}
return NULL; /* Never reached */
}
static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
{
/* Hang up a tree of stuff */
@@ -222,15 +396,19 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
(f->subclass == AST_CONTROL_BUSY))))
return -1;
if ((f->frametype == AST_FRAME_VOICE) ||
(f->frametype == AST_FRAME_DTMF)) {
if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect) {
(f->frametype == AST_FRAME_DTMF) ||
(f->frametype == AST_FRAME_TEXT)) {
if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
(f->subclass == '#')) {
if (f->subclass == '#') {
memset(newext, 0, sizeof(newext));
ptr = newext;
len = ast_pbx_longest_extension(chan->context) + 1;
if (len < ast_pbx_longest_extension("default") + 1)
len = ast_pbx_longest_extension("default") + 1;
/* Transfer */
if ((res=ast_streamfile(peer, "pbx-transfer")))
if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
break;
if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0)
break;
@@ -244,15 +422,35 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
res = ast_readstring(peer, ptr, len, 3000, 2000, "#");
if (res)
break;
if (ast_exists_extension(chan, chan->context, newext, 1)) {
/* Set the channel's new extension, since it exists */
if (!strcmp(newext, parking_ext)) {
if (!park_call(chan, peer)) {
/* We return non-zero, but tell the PBX not to hang the channel when
the thread dies -- We have to be careful now though. We are responsible for
hanging up the channel, else it will never be hung up! */
res=AST_PBX_KEEPALIVE;
break;
} else {
ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name);
}
/* XXX Maybe we should have another message here instead of invalid extension XXX */
} else if (ast_exists_extension(chan, peer->context, newext, 1)) {
/* Set the channel's new extension, since it exists, using peer context */
strncpy(chan->exten, newext, sizeof(chan->exten));
strncpy(chan->context, peer->context, sizeof(chan->context));
chan->priority = 0;
ast_frfree(f);
res=0;
break;
} else if (ast_exists_extension(chan, "default", newext, 1)) {
/* Set the channel's new extension, since it exists, using peer context */
strncpy(chan->exten, newext, sizeof(chan->exten));
strncpy(chan->context, "default", sizeof(chan->context));
chan->priority = 0;
ast_frfree(f);
res=0;
break;
}
res = ast_streamfile(peer, "pbx-invalid");
res = ast_streamfile(peer, "pbx-invalid", chan->language);
if (res)
break;
res = ast_waitstream(peer, AST_DIGIT_ANY);
@@ -280,6 +478,63 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
return res;
}
static int park_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
struct ast_channel *peer=NULL, *nchan;
struct parkeduser *pu, *pl=NULL;
int park;
if (!data) {
ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
return -1;
}
LOCAL_USER_ADD(u);
park = atoi((char *)data);
pthread_mutex_lock(&parking_lock);
pu = parkinglot;
while(pu) {
if (pu->parkingnum == park) {
if (pl)
pl->next = pu->next;
else
parkinglot = pu->next;
break;
}
pu = pu->next;
}
pthread_mutex_unlock(&parking_lock);
if (pu) {
peer = pu->chan;
free(pu);
}
if (peer) {
/* Build a translator if necessary */
if (peer->format & chan->format)
nchan = chan;
else
nchan = ast_translator_create(chan, peer->format, AST_DIRECTION_BOTH);
/* This runs sorta backwards, since we give the incoming channel control, as if it
were the person called. */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
res = bridge_call(peer, nchan, 1);
if (nchan != chan)
ast_translator_destroy(nchan);
/* Simulate the PBX hanging up */
if (res != AST_PBX_KEEPALIVE)
ast_hangup(peer);
return -1;
} else {
/* XXX Play a message XXX */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static int dial_exec(struct ast_channel *chan, void *data)
{
int res=-1;
@@ -290,6 +545,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
int to;
int allowredir=0;
char numsubst[AST_MAX_EXTENSION];
char restofit[AST_MAX_EXTENSION];
char *newnum;
if (!data) {
@@ -329,7 +585,8 @@ static int dial_exec(struct ast_channel *chan, void *data)
strncpy(numsubst, number, sizeof(numsubst));
/* If we're dialing by extension, look at the extension to know what to dial */
if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s", chan->exten);
strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit));
snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
/* By default, if we're dialing by extension, don't permit redirecting */
tmp->allowredirect = 0;
if (option_debug)
@@ -412,7 +669,24 @@ int unload_module(void)
int load_module(void)
{
return ast_register_application(app, dial_exec);
int res;
int x;
struct ast_context *con;
char exten[AST_MAX_EXTENSION];
con = ast_context_find(parking_con);
if (!con) {
ast_log(LOG_ERROR, "Parking context '%s' does not exist\n", parking_con);
return -1;
}
for(x=parking_start; x<=parking_stop;x++) {
snprintf(exten, sizeof(exten), "%d", x);
ast_add_extension2(con, 1, exten, 1, parkedcall, strdup(exten), free);
}
pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
res = ast_register_application(parkedcall, park_exec);
if (!res)
res = ast_register_application(app, dial_exec);
return res;
}
char *description(void)

14
apps/app_directory.c Executable file → Normal file
View File

@@ -156,17 +156,17 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
if (v) {
/* We have a match -- play a greeting if they have it */
snprintf(fn, sizeof(fn), "%s/vm/%s/greet", AST_SPOOL_DIR, v->name);
if (ast_fileexists(fn, NULL)) {
res = ast_streamfile(chan, fn);
if (ast_fileexists(fn, NULL, chan->language)) {
res = ast_streamfile(chan, fn, chan->language);
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
} else {
res = ast_say_digit_str(chan, v->name);
res = ast_say_digit_str(chan, v->name, chan->language);
}
ahem:
if (!res)
res = ast_streamfile(chan, "dir-instr");
res = ast_streamfile(chan, "dir-instr", chan->language);
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
if (!res)
@@ -189,9 +189,9 @@ ahem:
}
} else {
if (found)
res = ast_streamfile(chan, "dir-nomore");
res = ast_streamfile(chan, "dir-nomore", chan->language);
else
res = ast_streamfile(chan, "dir-nomatch");
res = ast_streamfile(chan, "dir-nomatch", chan->language);
if (!res)
res = 1;
return res;
@@ -219,7 +219,7 @@ static int directory_exec(struct ast_channel *chan, void *data)
LOCAL_USER_ADD(u);
top:
if (!res)
res = ast_streamfile(chan, "dir-intro");
res = ast_streamfile(chan, "dir-intro", chan->language);
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);

80
apps/app_echo.c Normal file
View File

@@ -0,0 +1,80 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Echo application -- play back what you hear to evaluate latency
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Simple Echo Application";
static char *app = "Echo";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int skel_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
struct ast_frame *f;
LOCAL_USER_ADD(u);
/* Do our thing here */
while((f = ast_read(chan))) {
if (f->frametype == AST_FRAME_VOICE) {
if (ast_write(chan, f))
break;
} else if (f->frametype == AST_FRAME_DTMF) {
if (f->subclass == '#') {
res = 0;
break;
} else
if (ast_write(chan, f))
break;
}
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, skel_exec);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}

6
apps/app_intercom.c Executable file → Normal file
View File

@@ -59,7 +59,7 @@ static int write_audio(short *data, int len)
pthread_mutex_unlock(&sound_lock);
return -1;
}
res = write(sound, data, len);
res = write(sound, data, len);
pthread_mutex_unlock(&sound_lock);
return res;
}
@@ -97,7 +97,7 @@ static int create_audio()
return -1;
}
if (fmt != desired) {
ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n");
ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n", desired, fmt);
}
#if 1
/* 2 bytes * 15 units of 2^5 = 32 bytes per buffer */
@@ -146,7 +146,7 @@ static int intercom_exec(struct ast_channel *chan, void *data)
res = 0;
} else
ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass);
}
}
}
ast_frfree(f);
} else

0
apps/app_mp3.c Executable file → Normal file
View File

16
apps/app_playback.c Executable file → Normal file
View File

@@ -31,18 +31,22 @@ LOCAL_USER_DECL;
static int playback_exec(struct ast_channel *chan, void *data)
{
int res;
int res = 0;
struct localuser *u;
if (!data) {
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
return -1;
}
LOCAL_USER_ADD(u);
ast_stopstream(chan);
res = ast_streamfile(chan, (char *)data);
if (!res)
res = ast_waitstream(chan, "");
ast_stopstream(chan);
if (chan->state != AST_STATE_UP)
res = ast_answer(chan);
if (!res) {
ast_stopstream(chan);
res = ast_streamfile(chan, (char *)data, chan->language);
if (!res)
res = ast_waitstream(chan, "");
ast_stopstream(chan);
}
LOCAL_USER_REMOVE(u);
return res;
}

50
apps/app_skel.c Executable file → Normal file
View File

@@ -15,6 +15,7 @@
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
@@ -22,63 +23,32 @@
#include <pthread.h>
static pthread_mutex_t skellock = PTHREAD_MUTEX_INITIALIZER;
static int usecnt=0;
static char *tdesc = "Trivial skeleton Application";
static char *app = "skel";
struct skeluser {
struct ast_channel *chan;
struct skeluser *next;
} *users = NULL;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int skel_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct skeluser *u, *ul=NULL;
struct localuser *u;
if (!data) {
ast_log(LOG_WARNING, "skel requires an argument (filename)\n");
return -1;
}
if (!(u=malloc(sizeof(struct skeluser)))) {
ast_log(LOG_WARNING, "Out of memory\n");
return -1;
}
pthread_mutex_lock(&skellock);
u->chan = chan;
u->next = users;
users = u;
usecnt++;
pthread_mutex_unlock(&skellock);
LOCAL_USER_ADD(u);
/* Do our thing here */
pthread_mutex_lock(&skellock);
u = users;
while(u) {
if (ul)
ul->next = u->next;
else
users = u->next;
u = u->next;
}
usecnt--;
pthread_mutex_unlock(&skellock);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
struct skeluser *u;
pthread_mutex_lock(&skellock);
u = users;
while(u) {
/* Hang up anybody who is using us */
ast_softhangup(u->chan);
u = u->next;
}
pthread_mutex_unlock(&skellock);
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
@@ -95,8 +65,6 @@ char *description(void)
int usecount(void)
{
int res;
pthread_mutex_lock(&skellock);
res = usecnt;
pthread_mutex_unlock(&skellock);
STANDARD_USECOUNT(res);
return res;
}

82
apps/app_system.c Normal file
View File

@@ -0,0 +1,82 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Execute arbitrary system commands
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Generic System() application";
static char *app = "System";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int skel_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
if (!data) {
ast_log(LOG_WARNING, "System requires an argument(command)\n");
return -1;
}
LOCAL_USER_ADD(u);
/* Do our thing here */
res = system((char *)data);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to execute '%s'\n", data);
res = -1;
} else if (res == 127) {
ast_log(LOG_WARNING, "Unable to execute '%s'\n", data);
res = -1;
} else {
if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101))
chan->priority+=100;
res = 0;
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, skel_exec);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}

75
apps/app_voicemail.c Executable file → Normal file
View File

@@ -81,15 +81,15 @@ static int announce_message(struct ast_channel *chan, char *dir, int msgcnt)
{
char *fn;
int res;
res = ast_streamfile(chan, "vm-message");
res = ast_streamfile(chan, "vm-message", chan->language);
if (!res) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
if (!res) {
res = ast_say_number(chan, msgcnt+1);
res = ast_say_number(chan, msgcnt+1, chan->language);
if (!res) {
fn = get_fn(dir, msgcnt);
if (fn) {
res = ast_streamfile(chan, fn);
res = ast_streamfile(chan, fn, chan->language);
free(fn);
}
}
@@ -141,7 +141,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
struct ast_config *cfg;
char *copy, *name, *passwd, *email, *dir, *fmt, *fmts, *fn=NULL;
char comment[256];
struct ast_filestream *writer, *others[MAX_OTHER_FORMATS];
struct ast_filestream *writer=NULL, *others[MAX_OTHER_FORMATS];
char *sfmt[MAX_OTHER_FORMATS];
int res = -1, fmtcnt=0, x;
int msgnum;
@@ -167,7 +167,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
if (mkdir(dir, 0700) && (errno != EEXIST))
ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
/* Stream an info message */
if (silent || !ast_streamfile(chan, INTRO)) {
if (silent || !ast_streamfile(chan, INTRO, chan->language)) {
/* Wait for the message to finish */
if (silent || !ast_waitstream(chan, "")) {
fmt = ast_variable_retrieve(cfg, "general", "format");
@@ -182,8 +182,12 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
snprintf(comment, sizeof(comment), "Voicemail from %s to %s (%s) on %s\n",
(chan->callerid ? chan->callerid : "Unknown"),
name, ext, chan->name);
if (ast_fileexists(fn, NULL, chan->language) > 0) {
msgnum++;
continue;
}
writer = ast_writefile(fn, fmt, comment, O_EXCL, 1 /* check for other formats */, 0700);
if (!writer && (errno != EEXIST))
if (!writer)
break;
msgnum++;
} while(!writer && (msgnum < MAXMSG));
@@ -221,9 +225,14 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
if (f->frametype == AST_FRAME_VOICE) {
/* Write the primary format */
res = ast_writestream(writer, f);
if (res) {
ast_log(LOG_WARNING, "Error writing primary frame\n");
break;
}
/* And each of the others */
for (x=0;x<fmtcnt;x++)
for (x=0;x<fmtcnt;x++) {
res |= ast_writestream(others[x], f);
}
ast_frfree(f);
/* Exit on any error */
if (res) {
@@ -259,7 +268,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent)
if (outmsg) {
if (outmsg > 1) {
/* Let them know it worked */
ast_streamfile(chan, "vm-msgsaved");
ast_streamfile(chan, "vm-msgsaved", chan->language);
ast_waitstream(chan, "");
}
/* Send e-mail if applicable */
@@ -314,20 +323,30 @@ static int vm_execmain(struct ast_channel *chan, void *data)
ast_log(LOG_WARNING, "No voicemail configuration\n");
goto out;
}
if (ast_streamfile(chan, "vm-login"))
if (ast_streamfile(chan, "vm-login", chan->language)) {
ast_log(LOG_WARNING, "Couldn't stream login file\n");
goto out;
}
do {
/* Prompt for, and read in the username */
if (ast_readstring(chan, username, sizeof(username), 2000, 5000, "#"))
if (ast_readstring(chan, username, sizeof(username), 2000, 5000, "#")) {
ast_log(LOG_WARNING, "Couldn't read username\n");
goto out;
}
if (!strlen(username)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Username not entered\n");
res = 0;
goto out;
}
if (ast_streamfile(chan, "vm-password"))
if (ast_streamfile(chan, "vm-password", chan->language)) {
ast_log(LOG_WARNING, "Unable to stream password file\n");
goto out;
if (ast_readstring(chan, password, sizeof(password), 2000, 5000, "#"))
}
if (ast_readstring(chan, password, sizeof(password), 2000, 5000, "#")) {
ast_log(LOG_WARNING, "Unable to read password\n");
goto out;
}
copy = ast_variable_retrieve(cfg, NULL, username);
if (copy) {
copy = strdup(copy);
@@ -340,7 +359,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
} else if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "No such user '%s' in config file\n", username);
if (!valid) {
if (ast_streamfile(chan, "vm-incorrect"))
if (ast_streamfile(chan, "vm-incorrect", chan->language))
break;
if (ast_waitstream(chan, ""))
break;
@@ -356,13 +375,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
not deleted. */
do {
fn = get_fn(dir, maxmsg);
if ((res = ast_fileexists(fn, NULL))>0) {
if ((res = ast_fileexists(fn, NULL, chan->language))>0) {
maxmsg++;
deleted[maxmsg] = 0;
}
free(fn);
} while(res > 0);
if (ast_streamfile(chan, "vm-youhave"))
if (ast_streamfile(chan, "vm-youhave", chan->language))
goto out;
if ((d=ast_waitstream(chan, AST_DIGIT_ANY)) < 0)
goto out;
@@ -370,10 +389,10 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (!d) {
/* If they haven't interrupted us, play the message count */
if (maxmsg > 0) {
if ((d = ast_say_number(chan, maxmsg)) < 0)
if ((d = ast_say_number(chan, maxmsg, chan->language)) < 0)
goto out;
} else {
if (ast_streamfile(chan, "vm-no"))
if (ast_streamfile(chan, "vm-no", chan->language))
goto out;
if ((d=ast_waitstream(chan, AST_DIGIT_ANY)) < 0)
goto out;
@@ -381,7 +400,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
}
if (!d) {
/* And if they still haven't, give them the last word */
if (ast_streamfile(chan, ((maxmsg == 1) ? "vm-message" : "vm-messages")))
if (ast_streamfile(chan, ((maxmsg == 1) ? "vm-message" : "vm-messages"), chan->language))
goto out;
if (ast_waitstream(chan, AST_DIGIT_ANY) < 0)
goto out;
@@ -397,7 +416,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
ast_log(LOG_EVENT, "User '%s' logged in on channel '%s' with %d message(s).\n", username, chan->name, maxmsg);
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "User '%s' logged in on channel %s with %d messages\n", username, chan->name, maxmsg);
if (!ast_streamfile(chan, "vm-instructions")) {
if (!ast_streamfile(chan, "vm-instructions", chan->language)) {
for(;;) {
if (chan->stream || (chan->trans && chan->trans->stream)) {
d = ast_waitstream(chan, AST_DIGIT_ANY);
@@ -405,7 +424,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (!d && (state == STATE_MESSAGE_PLAYING)) {
state = STATE_MESSAGE;
/* If it runs out playing a message, then give directions */
if (!(d = ast_streamfile(chan, "vm-msginstruct")))
if (!(d = ast_streamfile(chan, "vm-msginstruct", chan->language)))
d = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
}
@@ -421,12 +440,12 @@ restart:
best based up on where they are. Ditto if they press the '*' key. */
switch(state) {
case STATE_STARTING:
if (ast_streamfile(chan, "vm-instructions"))
if (ast_streamfile(chan, "vm-instructions", chan->language))
goto out;
break;
case STATE_MESSAGE:
case STATE_MESSAGE_PLAYING:
if (ast_streamfile(chan, "vm-msginstruct"))
if (ast_streamfile(chan, "vm-msginstruct", chan->language))
goto out;
break;
default:
@@ -441,14 +460,14 @@ restart:
if (curmsg < maxmsg) {
deleted[curmsg] = !deleted[curmsg];
if (deleted[curmsg]) {
if (ast_streamfile(chan, "vm-deleted"))
if (ast_streamfile(chan, "vm-deleted", chan->language))
goto out;
} else {
if (ast_streamfile(chan, "vm-undeleted"))
if (ast_streamfile(chan, "vm-undeleted", chan->language))
goto out;
}
} else {
if (ast_streamfile(chan, "vm-nomore"))
if (ast_streamfile(chan, "vm-nomore", chan->language))
goto out;
}
break;
@@ -461,7 +480,7 @@ restart:
else if (d < 0)
goto out;
} else {
if (ast_streamfile(chan, "vm-nomore"))
if (ast_streamfile(chan, "vm-nomore", chan->language))
goto out;
}
state = STATE_MESSAGE_PLAYING;
@@ -491,7 +510,7 @@ restart:
else if (d < 0)
goto out;
} else {
if (ast_streamfile(chan, "vm-nomore"))
if (ast_streamfile(chan, "vm-nomore", chan->language))
goto out;
}
state = STATE_MESSAGE_PLAYING;
@@ -499,7 +518,7 @@ restart:
/* XXX Message compose? It's easy! Just read their # and, assuming it's in the config,
call the routine as if it were called from the PBX proper XXX */
case '#':
if (ast_streamfile(chan, "vm-goodbye"))
if (ast_streamfile(chan, "vm-goodbye", chan->language))
goto out;
if (ast_waitstream(chan, ""))
goto out;

81
asterisk.c Executable file → Normal file
View File

@@ -16,6 +16,7 @@
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/cli.h>
#include <asterisk/channel.h>
#include <stdio.h>
#include <signal.h>
#include <sched.h>
@@ -28,7 +29,11 @@ int option_verbose=0;
int option_debug=0;
int option_nofork=0;
int option_quiet=0;
int option_console=0;
int option_highpriority=0;
int fully_booted = 0;
char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
#define HIGH_PRIORITY 1
#define HIGH_PRIORITY_SCHED SCHED_RR
@@ -39,6 +44,7 @@ static void urg_handler(int num)
system call. We don't actually need to do anything though. */
if (option_debug)
ast_log(LOG_DEBUG, "Urgent handler\n");
signal(num, urg_handler);
return;
}
@@ -89,6 +95,7 @@ static void console_verboser(char *s, int pos, int replace, int complete)
if (!pos)
fprintf(stdout, "\r");
fprintf(stdout, s + pos);
fflush(stdout);
if (complete)
/* Wake up a select()ing console */
pthread_kill(consolethread, SIGURG);
@@ -99,8 +106,19 @@ static void consolehandler(char *s)
/* Called when readline data is available */
if (s && strlen(s))
add_history(s);
if (s)
/* Give the console access to the shell */
if (s) {
if (s[0] == '!') {
if (s[1])
system(s+1);
else
system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
} else
ast_cli_command(STDOUT_FILENO, s);
if (!strcasecmp(s, "help"))
fprintf(stdout, " !<command> Executes a given shell command\n");
} else
fprintf(stdout, "\nUse \"quit\" to exit\n");
}
static char quit_help[] =
@@ -138,17 +156,21 @@ int main(int argc, char *argv[])
exit(1);
}
/* Check for options */
while((c=getopt(argc, argv, "dvqp")) != EOF) {
while((c=getopt(argc, argv, "dvqpc")) != EOF) {
switch(c) {
case 'd':
option_debug++;
option_nofork++;
break;
case 'c':
option_console++;
option_nofork++;
case 'p':
option_highpriority++;
break;
case 'v':
option_verbose++;
option_nofork++;
break;
case 'q':
option_quiet++;
@@ -157,12 +179,15 @@ int main(int argc, char *argv[])
exit(1);
}
}
ast_register_verbose(console_verboser);
/* Print a welcome message if desired */
if (option_verbose) {
if (option_verbose || option_console) {
ast_verbose( "Asterisk, Copyright (C) 1999 Mark Spencer\n");
ast_verbose( "Written by Mark Spencer <markster@linux-support.net>\n");
ast_verbose( "=========================================================================\n");
}
if (option_console && !option_verbose)
ast_verbose("[ Booting...");
signal(SIGURG, urg_handler);
signal(SIGINT, quit_handler);
signal(SIGTERM, quit_handler);
@@ -177,28 +202,34 @@ int main(int argc, char *argv[])
exit(1);
/* We might have the option of showing a console, but for now just
do nothing... */
/* Console stuff now... */
/* Register our quit function */
ast_cli_register(&quit);
consolethread = pthread_self();
ast_register_verbose(console_verboser);
if (option_verbose)
if (option_console && !option_verbose)
ast_verbose(" ]\n");
if (option_verbose || option_console)
ast_verbose( "Asterisk Ready.\n");
if (strlen(filename))
read_history(filename);
rl_callback_handler_install(ASTERISK_PROMPT, consolehandler);
rl_completion_entry_function = (Function *)cli_generator;
for(;;) {
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
res = select(STDIN_FILENO + 1, &rfds, NULL, NULL, NULL);
if (res > 0) {
rl_callback_read_char();
} else if (res < 1) {
rl_forced_update_display();
}
}
fully_booted = 1;
if (option_console) {
/* Console stuff now... */
/* Register our quit function */
ast_cli_register(&quit);
consolethread = pthread_self();
if (strlen(filename))
read_history(filename);
rl_callback_handler_install(ASTERISK_PROMPT, consolehandler);
rl_completion_entry_function = (Function *)cli_generator;
for(;;) {
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
res = select(STDIN_FILENO + 1, &rfds, NULL, NULL, NULL);
if (res > 0) {
rl_callback_read_char();
} else if (res < 1) {
rl_forced_update_display();
}
}
} else {
/* Do nothing */
select(0,NULL,NULL,NULL,NULL);
}
return 0;
}

2
asterisk.h Executable file → Normal file
View File

@@ -14,6 +14,8 @@
#ifndef _ASTERISK_H
#define _ASTERISK_H
#define DEFAULT_LANGUAGE "en"
#define AST_CONFIG_DIR "/etc/asterisk"
#define AST_MODULE_DIR "/usr/lib/asterisk/modules"
#define AST_SPOOL_DIR "/var/spool/asterisk"

0
audiofile.patch Executable file → Normal file
View File

72
channel.c Executable file → Normal file
View File

@@ -18,6 +18,7 @@
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <asterisk/sched.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
@@ -26,6 +27,27 @@
#include <asterisk/file.h>
#include <asterisk/translate.h>
#ifdef DEBUG_MUTEX
/* Convenient mutex debugging functions */
#define PTHREAD_MUTEX_LOCK(a) __PTHREAD_MUTEX_LOCK(__FUNCTION__, a)
#define PTHREAD_MUTEX_UNLOCK(a) __PTHREAD_MUTEX_UNLOCK(__FUNCTION__, a)
static int __PTHREAD_MUTEX_LOCK(char *f, pthread_mutex_t *a) {
ast_log(LOG_DEBUG, "Locking %p (%s)\n", a, f);
return pthread_mutex_lock(a);
}
static int __PTHREAD_MUTEX_UNLOCK(char *f, pthread_mutex_t *a) {
ast_log(LOG_DEBUG, "Unlocking %p (%s)\n", a, f);
return pthread_mutex_unlock(a);
}
#else
#define PTHREAD_MUTEX_LOCK(a) pthread_mutex_lock(a)
#define PTHREAD_MUTEX_UNLOCK(a) pthread_mutex_unlock(a)
#endif
struct chanlist {
char type[80];
char description[80];
@@ -33,7 +55,6 @@ struct chanlist {
struct ast_channel * (*requester)(char *type, int format, void *data);
struct chanlist *next;
} *backends = NULL;
struct ast_channel *channels = NULL;
/* Protect the channel list (highly unlikely that two things would change
@@ -45,7 +66,7 @@ int ast_channel_register(char *type, char *description, int capabilities,
struct ast_channel *(*requester)(char *type, int format, void *data))
{
struct chanlist *chan, *last=NULL;
if (pthread_mutex_lock(&chlock)) {
if (PTHREAD_MUTEX_LOCK(&chlock)) {
ast_log(LOG_WARNING, "Unable to lock channel list\n");
return -1;
}
@@ -53,7 +74,7 @@ int ast_channel_register(char *type, char *description, int capabilities,
while(chan) {
if (!strcasecmp(type, chan->type)) {
ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
return -1;
}
last = chan;
@@ -62,7 +83,7 @@ int ast_channel_register(char *type, char *description, int capabilities,
chan = malloc(sizeof(struct chanlist));
if (!chan) {
ast_log(LOG_WARNING, "Out of memory\n");
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
return -1;
}
strncpy(chan->type, type, sizeof(chan->type));
@@ -78,7 +99,7 @@ int ast_channel_register(char *type, char *description, int capabilities,
ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
else if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
return 0;
}
@@ -86,7 +107,7 @@ struct ast_channel *ast_channel_alloc(void)
{
struct ast_channel *tmp;
struct ast_channel_pvt *pvt;
pthread_mutex_lock(&chlock);
PTHREAD_MUTEX_LOCK(&chlock);
tmp = malloc(sizeof(struct ast_channel));
memset(tmp, 0, sizeof(struct ast_channel));
if (tmp) {
@@ -105,6 +126,7 @@ struct ast_channel *ast_channel_alloc(void)
tmp->data = NULL;
pthread_mutex_init(&tmp->lock, NULL);
strncpy(tmp->context, "default", sizeof(tmp->context));
strncpy(tmp->language, defaultlanguage, sizeof(tmp->language));
strncpy(tmp->exten, "s", sizeof(tmp->exten));
tmp->priority=1;
tmp->next = channels;
@@ -121,17 +143,17 @@ struct ast_channel *ast_channel_alloc(void)
}
} else
ast_log(LOG_WARNING, "Out of memory\n");
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
return tmp;
}
struct ast_channel *ast_channel_walk(struct ast_channel *prev)
{
struct ast_channel *l, *ret=NULL;
pthread_mutex_lock(&chlock);
PTHREAD_MUTEX_LOCK(&chlock);
l = channels;
if (!prev) {
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
return l;
}
while(l) {
@@ -139,7 +161,7 @@ struct ast_channel *ast_channel_walk(struct ast_channel *prev)
ret = l->next;
l = l->next;
}
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
return ret;
}
@@ -147,7 +169,7 @@ struct ast_channel *ast_channel_walk(struct ast_channel *prev)
void ast_channel_free(struct ast_channel *chan)
{
struct ast_channel *last=NULL, *cur;
pthread_mutex_lock(&chlock);
PTHREAD_MUTEX_LOCK(&chlock);
cur = channels;
while(cur) {
if (cur == chan) {
@@ -174,7 +196,7 @@ void ast_channel_free(struct ast_channel *chan)
free(chan->callerid);
pthread_mutex_destroy(&chan->lock);
free(chan);
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
}
int ast_softhangup(struct ast_channel *chan)
@@ -220,7 +242,7 @@ void ast_channel_unregister(char *type)
struct chanlist *chan, *last=NULL;
if (option_debug)
ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
if (pthread_mutex_lock(&chlock)) {
if (PTHREAD_MUTEX_LOCK(&chlock)) {
ast_log(LOG_WARNING, "Unable to lock channel list\n");
return;
}
@@ -232,13 +254,13 @@ void ast_channel_unregister(char *type)
else
backends = backends->next;
free(chan);
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
return;
}
last = chan;
chan = chan->next;
}
pthread_mutex_unlock(&chlock);
PTHREAD_MUTEX_UNLOCK(&chlock);
}
int ast_answer(struct ast_channel *chan)
@@ -366,6 +388,16 @@ struct ast_frame *ast_read(struct ast_channel *chan)
return f;
}
int ast_sendtext(struct ast_channel *chan, char *text)
{
int res = 0;
CHECK_BLOCKING(chan);
if (chan->pvt->send_text)
res = chan->pvt->send_text(chan, text);
chan->blocking = 0;
return res;
}
int ast_write(struct ast_channel *chan, struct ast_frame *fr)
{
int res = -1;
@@ -392,7 +424,7 @@ struct ast_channel *ast_request(char *type, int format, void *data)
{
struct chanlist *chan;
struct ast_channel *c = NULL;
if (pthread_mutex_lock(&chlock)) {
if (PTHREAD_MUTEX_LOCK(&chlock)) {
ast_log(LOG_WARNING, "Unable to lock channel list\n");
return NULL;
}
@@ -402,15 +434,16 @@ struct ast_channel *ast_request(char *type, int format, void *data)
if (!(chan->capabilities & format)) {
format = ast_translator_best_choice(format, chan->capabilities);
}
PTHREAD_MUTEX_UNLOCK(&chlock);
if (chan->requester)
c = chan->requester(type, format, data);
pthread_mutex_unlock(&chlock);
break;
return c;
}
chan = chan->next;
}
if (!chan)
ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
PTHREAD_MUTEX_UNLOCK(&chlock);
return c;
}
@@ -433,9 +466,10 @@ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int fti
if (!len)
return -1;
do {
if (c->streamid > -1) {
if ((c->streamid > -1) || (c->trans && (c->trans->streamid > -1))) {
d = ast_waitstream(c, AST_DIGIT_ANY);
ast_stopstream(c);
usleep(1000);
if (!d)
d = ast_waitfordigit(c, to);
} else {

0
channels/DialTone.h Executable file → Normal file
View File

10
channels/Makefile Executable file → Normal file
View File

@@ -11,7 +11,12 @@
# the GNU General Public License
#
CHANNEL_LIBS=chan_vofr.so chan_ixj.so chan_modem.so chan_modem_aopen.so
CHANNEL_LIBS=chan_vofr.so chan_modem.so \
chan_modem_aopen.so chan_iax.so chan_oss.so
CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/ixjuser.h ] && echo chan_phone.so)
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
CFLAGS+=#-DVOFRDUMPER
@@ -23,5 +28,8 @@ clean:
%.so : %.o
$(CC) -shared -Xlinker -x -o $@ $<
#chan_modem.so : chan_modem.o
# $(CC) -rdynamic -shared -Xlinker -x -o $@ $<
install: all
for x in $(CHANNEL_LIBS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done

0
channels/adtranvofr.h Executable file → Normal file
View File

2247
channels/chan_iax.c Normal file

File diff suppressed because it is too large Load Diff

29
channels/chan_modem.c Executable file → Normal file
View File

@@ -49,6 +49,9 @@ static char mtype[80] = "autodetect";
/* Default context for incoming calls */
static char context[AST_MAX_EXTENSION]= "default";
/* Default language */
static char language[MAX_LANGUAGE] = "";
/* Initialization String */
static char initstr[AST_MAX_INIT_STR] = "ATE1Q0";
@@ -271,8 +274,13 @@ static int modem_setup(struct ast_modem_pvt *p, int baudrate)
mode. Set the baud rate, etc. */
char identity[256];
char *ident = NULL;
char etx[2] = { 0x10, 0x03 };
if (option_debug)
ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev);
if (ast_modem_send(p, etx, 2)) {
ast_log(LOG_WARNING, "Failed to send ETX?\n");
return -1;
}
if (ast_modem_send(p, "\r\n", 2)) {
ast_log(LOG_WARNING, "Failed to send enter?\n");
return -1;
@@ -419,7 +427,6 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
tmp->type = type;
tmp->fd = i->fd;
/* XXX Switching formats silently causes kernel panics XXX */
tmp->format = i->mc->formats;
tmp->state = state;
if (state == AST_STATE_RING)
@@ -433,7 +440,9 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
tmp->pvt->write = modem_write;
strncpy(tmp->context, i->context, sizeof(tmp->context));
if (strlen(i->cid))
strncpy(tmp->callerid, i->cid, sizeof(tmp->callerid));
tmp->callerid = strdup(i->cid);
if (strlen(i->language))
strncpy(tmp->language,i->language, sizeof(tmp->language));
i->owner = tmp;
pthread_mutex_lock(&usecnt_lock);
usecnt++;
@@ -443,6 +452,7 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
ast_hangup(tmp);
tmp = NULL;
}
}
} else
@@ -454,6 +464,12 @@ static void modem_mini_packet(struct ast_modem_pvt *i)
{
struct ast_frame *fr;
fr = i->mc->read(i);
if (fr->frametype == AST_FRAME_CONTROL) {
if (fr->subclass == AST_CONTROL_RING) {
ast_modem_new(i, AST_STATE_RING);
restart_monitor();
}
}
}
static void *do_monitor(void *data)
@@ -590,6 +606,7 @@ static struct ast_modem_pvt *mkif(char *iface)
free(tmp);
return NULL;
}
strncpy(tmp->language, language, sizeof(tmp->language));
tmp->f = fdopen(tmp->fd, "w+");
/* Disable buffering */
setvbuf(tmp->f, NULL, _IONBF,0);
@@ -701,10 +718,10 @@ int load_module()
ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver);
if (ast_load_resource(driver)) {
ast_log(LOG_ERROR, "Failed to laod driver %s\n", driver);
ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
ast_destroy(cfg);
unload_module();
pthread_mutex_unlock(&iflock);
unload_module();
return -1;
}
} else if (!strcasecmp(v->name, "mode")) {
@@ -726,6 +743,8 @@ int load_module()
dialtype = toupper(v->value[0]);
} else if (!strcasecmp(v->name, "context")) {
strncpy(context, v->value, sizeof(context));
} else if (!strcasecmp(v->name, "language")) {
strncpy(language, v->value, sizeof(language));
}
v = v->next;
}
@@ -742,8 +761,6 @@ int load_module()
return 0;
}
int unload_module()
{
struct ast_modem_pvt *p, *pl;

13
channels/chan_modem_aopen.c Executable file → Normal file
View File

@@ -194,9 +194,13 @@ static struct ast_frame *aopen_handle_escape(struct ast_modem_pvt *p, char esc)
ast_log(LOG_DEBUG, "Escaped character '%c'\n", esc);
switch(esc) {
case 'R': /* Pseudo ring */
p->fr.frametype = AST_FRAME_CONTROL;
p->fr.subclass = AST_CONTROL_RING;
return &p->fr;
case 'X': /* Pseudo connect */
p->fr.frametype = AST_FRAME_CONTROL;
p->fr.subclass = AST_CONTROL_ANSWER;
p->fr.subclass = AST_CONTROL_RING;
if (p->owner)
p->owner->state = AST_STATE_UP;
if (aopen_startrec(p))
@@ -255,11 +259,14 @@ static struct ast_frame *aopen_read(struct ast_modem_pvt *p)
/* If we're in immediate mode, reply now */
if (p->mode == MODEM_MODE_IMMEDIATE)
return aopen_handle_escape(p, 'X');
}
} else
if (!strcasecmp(result, "BUSY")) {
/* Same as a busy signal */
return aopen_handle_escape(p, 'b');
}
} else
if (!strcasecmp(result, "RING")) {
return aopen_handle_escape(p, 'R');
} else
if (!strcasecmp(result, "NO DIALTONE")) {
/* There's no dialtone, so the line isn't working */
ast_log(LOG_WARNING, "Device '%s' lacking dialtone\n", p->dev);

843
channels/chan_oss.c Normal file
View File

@@ -0,0 +1,843 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Use /dev/dsp as a channel, and the console to command it :).
*
* The full-duplex "simulation" is pretty weak. This is generally a
* VERY BADLY WRITTEN DRIVER so please don't use it as a model for
* writing a driver.
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/frame.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/module.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/options.h>
#include <asterisk/pbx.h>
#include <asterisk/config.h>
#include <asterisk/cli.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>
/* Which device to use */
#define DEV_DSP "/dev/dsp"
/* Lets use 160 sample frames, just like GSM. */
#define FRAME_SIZE 160
/* When you set the frame size, you have to come up with
the right buffer format as well. */
/* 5 64-byte frames = one frame */
#define BUFFER_FMT ((buffersize * 5) << 16) | (0x0006);
/* Don't switch between read/write modes faster than every 300 ms */
#define MIN_SWITCH_TIME 600
static struct timeval lasttime;
static int usecnt;
static int needanswer = 0;
static int needhangup = 0;
static int silencesuppression = 0;
static int silencethreshold = 1000;
static char digits[80] = "";
static char text2send[80] = "";
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
static char *type = "Console";
static char *desc = "OSS Console Channel Driver";
static char *tdesc = "OSS Console Channel Driver";
static char *config = "oss.conf";
static char context[AST_MAX_EXTENSION] = "default";
static char language[MAX_LANGUAGE] = "";
static char exten[AST_MAX_EXTENSION] = "s";
/* Some pipes to prevent overflow */
static int funnel[2];
static pthread_mutex_t sound_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t silly;
static struct chan_oss_pvt {
/* We only have one OSS structure -- near sighted perhaps, but it
keeps this driver as simple as possible -- as it should be. */
struct ast_channel *owner;
char exten[AST_MAX_EXTENSION];
char context[AST_MAX_EXTENSION];
} oss;
static int time_has_passed()
{
struct timeval tv;
int ms;
gettimeofday(&tv, NULL);
ms = (tv.tv_sec - lasttime.tv_sec) * 1000 +
(tv.tv_usec - lasttime.tv_usec) / 1000;
if (ms > MIN_SWITCH_TIME)
return -1;
return 0;
}
/* Number of buffers... Each is FRAMESIZE/8 ms long. For example
with 160 sample frames, and a buffer size of 3, we have a 60ms buffer,
usually plenty. */
#define MAX_BUFFER_SIZE 100
static int buffersize = 3;
static int full_duplex = 0;
/* Are we reading or writing (simulated full duplex) */
static int readmode = 1;
/* File descriptor for sound device */
static int sounddev = -1;
static int autoanswer = 1;
static int calc_loudness(short *frame)
{
int sum = 0;
int x;
for (x=0;x<FRAME_SIZE;x++) {
if (frame[x] < 0)
sum -= frame[x];
else
sum += frame[x];
}
sum = sum/FRAME_SIZE;
return sum;
}
static int silence_suppress(short *buf)
{
#define SILBUF 3
int loudness;
static int silentframes = 0;
static char silbuf[FRAME_SIZE * 2 * SILBUF];
static int silbufcnt=0;
if (!silencesuppression)
return 0;
loudness = calc_loudness((short *)(buf));
if (option_debug)
ast_log(LOG_DEBUG, "loudness is %d\n", loudness);
if (loudness < silencethreshold) {
silentframes++;
silbufcnt++;
/* Keep track of the last few bits of silence so we can play
them as lead-in when the time is right */
if (silbufcnt >= SILBUF) {
/* Make way for more buffer */
memmove(silbuf, silbuf + FRAME_SIZE * 2, FRAME_SIZE * 2 * (SILBUF - 1));
silbufcnt--;
}
memcpy(silbuf + FRAME_SIZE * 2 * silbufcnt, buf, FRAME_SIZE * 2);
if (silentframes > 10) {
/* We've had plenty of silence, so compress it now */
return 1;
}
} else {
silentframes=0;
/* Write any buffered silence we have, it may have something
important */
if (silbufcnt) {
write(funnel[1], silbuf, silbufcnt * FRAME_SIZE);
silbufcnt = 0;
}
}
return 0;
}
static void *silly_thread(void *ignore)
{
char buf[FRAME_SIZE * 2];
int pos=0;
int res=0;
/* Read from the sound device, and write to the pipe. */
for (;;) {
/* Give the writer a better shot at the lock */
#if 0
usleep(1000);
#endif
pthread_testcancel();
pthread_mutex_lock(&sound_lock);
res = read(sounddev, buf + pos, FRAME_SIZE * 2 - pos);
pthread_mutex_unlock(&sound_lock);
if (res > 0) {
pos += res;
if (pos == FRAME_SIZE * 2) {
if (needhangup || needanswer || strlen(digits) ||
!silence_suppress((short *)buf)) {
res = write(funnel[1], buf, sizeof(buf));
}
pos = 0;
}
} else {
close(funnel[1]);
break;
}
pthread_testcancel();
}
return NULL;
}
static int setformat(void)
{
int fmt, desired, res, fd = sounddev;
static int warnedalready = 0;
static int warnedalready2 = 0;
pthread_mutex_lock(&sound_lock);
fmt = AFMT_S16_LE;
res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
pthread_mutex_unlock(&sound_lock);
return -1;
}
res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
if (res >= 0) {
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
full_duplex = -1;
}
fmt = 0;
res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
pthread_mutex_unlock(&sound_lock);
return -1;
}
/* 8000 Hz desired */
desired = 8000;
fmt = desired;
res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
pthread_mutex_unlock(&sound_lock);
return -1;
}
if (fmt != desired) {
if (!warnedalready++)
ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n", desired, fmt);
}
#if 1
fmt = BUFFER_FMT;
res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
if (res < 0) {
if (!warnedalready2++)
ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n");
}
#endif
pthread_mutex_unlock(&sound_lock);
return 0;
}
static int soundcard_setoutput(int force)
{
/* Make sure the soundcard is in output mode. */
int fd = sounddev;
if (full_duplex || (!readmode && !force))
return 0;
pthread_mutex_lock(&sound_lock);
readmode = 0;
if (force || time_has_passed()) {
ioctl(sounddev, SNDCTL_DSP_RESET);
/* Keep the same fd reserved by closing the sound device and copying stdin at the same
time. */
/* dup2(0, sound); */
close(sounddev);
fd = open(DEV_DSP, O_WRONLY);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno));
pthread_mutex_unlock(&sound_lock);
return -1;
}
/* dup2 will close the original and make fd be sound */
if (dup2(fd, sounddev) < 0) {
ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno));
pthread_mutex_unlock(&sound_lock);
return -1;
}
if (setformat()) {
pthread_mutex_unlock(&sound_lock);
return -1;
}
pthread_mutex_unlock(&sound_lock);
return 0;
}
pthread_mutex_unlock(&sound_lock);
return 1;
}
static int soundcard_setinput(int force)
{
int fd = sounddev;
if (full_duplex || (readmode && !force))
return 0;
pthread_mutex_lock(&sound_lock);
readmode = -1;
if (force || time_has_passed()) {
ioctl(sounddev, SNDCTL_DSP_RESET);
close(sounddev);
/* dup2(0, sound); */
fd = open(DEV_DSP, O_RDONLY);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno));
pthread_mutex_unlock(&sound_lock);
return -1;
}
/* dup2 will close the original and make fd be sound */
if (dup2(fd, sounddev) < 0) {
ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno));
pthread_mutex_unlock(&sound_lock);
return -1;
}
if (setformat()) {
pthread_mutex_unlock(&sound_lock);
return -1;
}
pthread_mutex_unlock(&sound_lock);
return 0;
}
pthread_mutex_unlock(&sound_lock);
return 1;
}
static int soundcard_init()
{
/* Assume it's full duplex for starters */
int fd = open(DEV_DSP, O_RDWR);
if (fd < 0) {
ast_log(LOG_ERROR, "Unable to open %s: %s\n", DEV_DSP, strerror(errno));
return fd;
}
gettimeofday(&lasttime, NULL);
sounddev = fd;
setformat();
if (!full_duplex)
soundcard_setinput(1);
return sounddev;
}
static int oss_digit(struct ast_channel *c, char digit)
{
ast_verbose( " << Console Received digit %c >> \n", digit);
return 0;
}
static int oss_text(struct ast_channel *c, char *text)
{
ast_verbose( " << Console Received text %s >> \n", text);
return 0;
}
static int oss_call(struct ast_channel *c, char *dest, int timeout)
{
ast_verbose( " << Call placed to '%s' on console >> \n", dest);
if (autoanswer) {
ast_verbose( " << Auto-answered >> \n" );
needanswer = 1;
} else {
ast_verbose( " << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
}
return 0;
}
static int oss_answer(struct ast_channel *c)
{
ast_verbose( " << Console call has been answered >> \n");
c->state = AST_STATE_UP;
return 0;
}
static int oss_hangup(struct ast_channel *c)
{
c->pvt->pvt = NULL;
oss.owner = NULL;
ast_verbose( " << Hangup on console >> \n");
pthread_mutex_lock(&usecnt_lock);
usecnt--;
pthread_mutex_unlock(&usecnt_lock);
needhangup = 0;
needanswer = 0;
return 0;
}
static int soundcard_writeframe(short *data)
{
/* Write an exactly FRAME_SIZE sized of frame */
static int bufcnt = 0;
static char buffer[FRAME_SIZE * 2 * MAX_BUFFER_SIZE * 5];
struct audio_buf_info info;
int res;
int fd = sounddev;
static int warned=0;
pthread_mutex_lock(&sound_lock);
if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)) {
if (!warned)
ast_log(LOG_WARNING, "Error reading output space\n");
bufcnt = buffersize;
warned++;
}
if ((info.fragments >= buffersize * 5) && (bufcnt == buffersize)) {
/* We've run out of stuff, buffer again */
bufcnt = 0;
}
if (bufcnt == buffersize) {
/* Write sample immediately */
res = write(fd, ((void *)data), FRAME_SIZE * 2);
} else {
/* Copy the data into our buffer */
res = FRAME_SIZE * 2;
memcpy(buffer + (bufcnt * FRAME_SIZE * 2), data, FRAME_SIZE * 2);
bufcnt++;
if (bufcnt == buffersize) {
res = write(fd, ((void *)buffer), FRAME_SIZE * 2 * buffersize);
}
}
pthread_mutex_unlock(&sound_lock);
return res;
}
static int oss_write(struct ast_channel *chan, struct ast_frame *f)
{
int res;
static char sizbuf[8000];
static int sizpos = 0;
int len = sizpos;
int pos;
if (!full_duplex && (strlen(digits) || needhangup || needanswer)) {
/* If we're half duplex, we have to switch to read mode
to honor immediate needs if necessary */
res = soundcard_setinput(1);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set device to input mode\n");
return -1;
}
return 0;
}
res = soundcard_setoutput(0);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set output device\n");
return -1;
} else if (res > 0) {
/* The device is still in read mode, and it's too soon to change it,
so just pretend we wrote it */
return 0;
}
/* We have to digest the frame in 160-byte portions */
if (f->datalen > sizeof(sizbuf) - sizpos) {
ast_log(LOG_WARNING, "Frame too large\n");
return -1;
}
memcpy(sizbuf + sizpos, f->data, f->datalen);
len += f->datalen;
pos = 0;
while(len - pos > FRAME_SIZE * 2) {
soundcard_writeframe((short *)(sizbuf + pos));
pos += FRAME_SIZE * 2;
}
if (len - pos)
memmove(sizbuf, sizbuf + pos, len - pos);
sizpos = len - pos;
return 0;
}
static struct ast_frame *oss_read(struct ast_channel *chan)
{
static struct ast_frame f;
static char buf[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
static int readpos = 0;
int res;
#if 0
ast_log(LOG_DEBUG, "oss_read()\n");
#endif
f.frametype = AST_FRAME_NULL;
f.subclass = 0;
f.timelen = 0;
f.datalen = 0;
f.data = NULL;
f.offset = 0;
f.src = type;
f.mallocd = 0;
if (needhangup) {
return NULL;
}
if (strlen(text2send)) {
f.frametype = AST_FRAME_TEXT;
f.subclass = 0;
f.data = text2send;
f.datalen = strlen(text2send);
strcpy(text2send,"");
return &f;
}
if (strlen(digits)) {
f.frametype = AST_FRAME_DTMF;
f.subclass = digits[0];
for (res=0;res<strlen(digits);res++)
digits[res] = digits[res + 1];
return &f;
}
if (needanswer) {
needanswer = 0;
f.frametype = AST_FRAME_CONTROL;
f.subclass = AST_CONTROL_ANSWER;
chan->state = AST_STATE_UP;
return &f;
}
res = soundcard_setinput(0);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set input mode\n");
return NULL;
}
if (res > 0) {
/* Theoretically shouldn't happen, but anyway, return a NULL frame */
return &f;
}
res = read(funnel[0], buf + AST_FRIENDLY_OFFSET + readpos, FRAME_SIZE * 2 - readpos);
if (res < 0) {
ast_log(LOG_WARNING, "Error reading from sound device: %s\n", strerror(errno));
return NULL;
}
readpos += res;
if (readpos == FRAME_SIZE * 2) {
/* A real frame */
readpos = 0;
f.frametype = AST_FRAME_VOICE;
f.subclass = AST_FORMAT_SLINEAR;
f.timelen = FRAME_SIZE / 8;
f.datalen = FRAME_SIZE * 2;
f.data = buf + AST_FRIENDLY_OFFSET;
f.offset = AST_FRIENDLY_OFFSET;
f.src = type;
f.mallocd = 0;
}
return &f;
}
static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
{
struct ast_channel *tmp;
tmp = ast_channel_alloc();
if (tmp) {
snprintf(tmp->name, sizeof(tmp->name), "OSS/%s", DEV_DSP + 5);
tmp->type = type;
tmp->fd = funnel[0];
tmp->format = AST_FORMAT_SLINEAR;
tmp->pvt->pvt = p;
tmp->pvt->send_digit = oss_digit;
tmp->pvt->send_text = oss_text;
tmp->pvt->hangup = oss_hangup;
tmp->pvt->answer = oss_answer;
tmp->pvt->read = oss_read;
tmp->pvt->call = oss_call;
tmp->pvt->write = oss_write;
if (strlen(p->context))
strncpy(tmp->context, p->context, sizeof(tmp->context));
if (strlen(p->exten))
strncpy(tmp->exten, p->exten, sizeof(tmp->exten));
if (strlen(language))
strncpy(tmp->language, language, sizeof(tmp->language));
p->owner = tmp;
tmp->state = state;
pthread_mutex_lock(&usecnt_lock);
usecnt++;
pthread_mutex_unlock(&usecnt_lock);
ast_update_use_count();
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
ast_hangup(tmp);
tmp = NULL;
}
}
}
return tmp;
}
static struct ast_channel *oss_request(char *type, int format, void *data)
{
int oldformat = format;
struct ast_channel *tmp;
format &= AST_FORMAT_SLINEAR;
if (!format) {
ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat);
return NULL;
}
if (oss.owner) {
ast_log(LOG_NOTICE, "Already have a call on the OSS channel\n");
return NULL;
}
tmp= oss_new(&oss, AST_STATE_DOWN);
if (!tmp) {
ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
}
return tmp;
}
static int console_autoanswer(int fd, int argc, char *argv[])
{
if ((argc != 1) && (argc != 2))
return RESULT_SHOWUSAGE;
if (argc == 1) {
ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
return RESULT_SUCCESS;
} else {
if (!strcasecmp(argv[1], "on"))
autoanswer = -1;
else if (!strcasecmp(argv[1], "off"))
autoanswer = 0;
else
return RESULT_SHOWUSAGE;
}
return RESULT_SUCCESS;
}
static char *autoanswer_complete(char *line, char *word, int pos, int state)
{
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
switch(state) {
case 0:
if (strlen(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
return strdup("on");
case 1:
if (strlen(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
return strdup("off");
default:
return NULL;
}
return NULL;
}
static char autoanswer_usage[] =
"Usage: autoanswer [on|off]\n"
" Enables or disables autoanswer feature. If used without\n"
" argument, displays the current on/off status of autoanswer.\n"
" The default value of autoanswer is in 'oss.conf'.\n";
static int console_answer(int fd, int argc, char *argv[])
{
if (argc != 1)
return RESULT_SHOWUSAGE;
if (!oss.owner) {
ast_cli(fd, "No one is calling us\n");
return RESULT_FAILURE;
}
needanswer++;
return RESULT_SUCCESS;
}
static char sendtext_usage[] =
"Usage: send text <message>\n"
" Sends a text message for display on the remote terminal.\n";
static int console_sendtext(int fd, int argc, char *argv[])
{
int tmparg = 1;
if (argc < 1)
return RESULT_SHOWUSAGE;
if (!oss.owner) {
ast_cli(fd, "No one is calling us\n");
return RESULT_FAILURE;
}
if (strlen(text2send))
ast_cli(fd, "Warning: message already waiting to be sent, overwriting\n");
strcpy(text2send, "");
while(tmparg <= argc) {
strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send));
strncat(text2send, " ", sizeof(text2send) - strlen(text2send));
}
needanswer++;
return RESULT_SUCCESS;
}
static char answer_usage[] =
"Usage: answer\n"
" Answers an incoming call on the console (OSS) channel.\n";
static int console_hangup(int fd, int argc, char *argv[])
{
if (argc != 1)
return RESULT_SHOWUSAGE;
if (!oss.owner) {
ast_cli(fd, "No call to hangup up\n");
return RESULT_FAILURE;
}
needhangup++;
return RESULT_SUCCESS;
}
static char hangup_usage[] =
"Usage: hangup\n"
" Hangs up any call currently placed on the console.\n";
static int console_dial(int fd, int argc, char *argv[])
{
char tmp[256], *tmp2;
char *mye, *myc;
if ((argc != 1) && (argc != 2))
return RESULT_SHOWUSAGE;
if (oss.owner) {
if (argc == 2)
strncat(digits, argv[1], sizeof(digits) - strlen(digits));
else {
ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n");
return RESULT_FAILURE;
}
return RESULT_SUCCESS;
}
mye = exten;
myc = context;
if (argc == 2) {
strncpy(tmp, argv[1], sizeof(tmp));
strtok(tmp, "@");
tmp2 = strtok(NULL, "@");
if (strlen(tmp))
mye = tmp;
if (tmp2 && strlen(tmp2))
myc = tmp2;
}
if (ast_exists_extension(NULL, myc, mye, 1)) {
strncpy(oss.exten, mye, sizeof(oss.exten));
strncpy(oss.context, myc, sizeof(oss.context));
oss_new(&oss, AST_STATE_UP);
} else
ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
return RESULT_SUCCESS;
}
static char dial_usage[] =
"Usage: dial [extension[@context]]\n"
" Dials a given extensison (";
static struct ast_cli_entry myclis[] = {
{ { "answer", NULL }, console_answer, "Answer an incoming console call", answer_usage },
{ { "hangup", NULL }, console_hangup, "Hangup a call on the console", hangup_usage },
{ { "dial", NULL }, console_dial, "Dial an extension on the console", dial_usage },
{ { "send text", NULL }, console_sendtext, "Send text to the remote device", sendtext_usage },
{ { "autoanswer", NULL }, console_autoanswer, "Sets/displays autoanswer", autoanswer_usage, autoanswer_complete }
};
int load_module()
{
int res;
int x;
int flags;
struct ast_config *cfg = ast_load(config);
struct ast_variable *v;
res = pipe(funnel);
if (res) {
ast_log(LOG_ERROR, "Unable to create pipe\n");
return -1;
}
/* We make the funnel so that writes to the funnel don't block...
Our "silly" thread can read to its heart content, preventing
recording overruns */
flags = fcntl(funnel[1], F_GETFL);
#if 0
fcntl(funnel[0], F_SETFL, flags | O_NONBLOCK);
#endif
fcntl(funnel[1], F_SETFL, flags | O_NONBLOCK);
res = soundcard_init();
if (res < 0) {
close(funnel[1]);
close(funnel[0]);
return -1;
}
if (!full_duplex)
ast_log(LOG_WARNING, "XXX I don't work right with non-full duplex sound cards XXX\n");
pthread_create(&silly, NULL, silly_thread, NULL);
res = ast_channel_register(type, tdesc, AST_FORMAT_SLINEAR, oss_request);
if (res < 0) {
ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", type);
return -1;
}
for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
ast_cli_register(myclis + x);
if (cfg) {
v = ast_variable_browse(cfg, "general");
while(v) {
if (!strcasecmp(v->name, "autoanswer"))
autoanswer = ast_true(v->value);
else if (!strcasecmp(v->name, "silencesuppression"))
silencesuppression = ast_true(v->value);
else if (!strcasecmp(v->name, "silencethreshold"))
silencethreshold = atoi(v->value);
else if (!strcasecmp(v->name, "context"))
strncpy(context, v->value, sizeof(context));
else if (!strcasecmp(v->name, "language"))
strncpy(language, v->value, sizeof(language));
else if (!strcasecmp(v->name, "extension"))
strncpy(exten, v->value, sizeof(exten));
v=v->next;
}
ast_destroy(cfg);
}
return 0;
}
int unload_module()
{
int x;
for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
ast_cli_unregister(myclis + x);
close(sounddev);
if (funnel[0] > 0) {
close(funnel[0]);
close(funnel[1]);
}
if (silly) {
pthread_cancel(silly);
pthread_join(silly, NULL);
}
if (oss.owner)
ast_softhangup(oss.owner);
if (oss.owner)
return -1;
return 0;
}
char *description()
{
return desc;
}
int usecount()
{
int res;
pthread_mutex_lock(&usecnt_lock);
res = usecnt;
pthread_mutex_unlock(&usecnt_lock);
return res;
}

389
channels/chan_ixj.c → channels/chan_phone.c Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* QuickNet Internet Phone Jack Channel
* Generic Linux Telephony Interface driver
*
* Copyright (C) 1999, Mark Spencer
*
@@ -29,27 +29,34 @@
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include "ixjuser.h"
#include <linux/telephony.h>
/* Still use some IXJ specific stuff */
#include <linux/ixjuser.h>
#include "DialTone.h"
#define IXJ_MAX_BUF 480
#define phone_MAX_BUF 480
static char *desc = "QuickNet Internet Phone Jack";
static char *type = "PhoneJack";
static char *tdesc = "QuickNet Internet Phone Jack";
static char *config = "ixj.conf";
static char *desc = "Linux Telephony API Support";
static char *type = "Phone";
static char *tdesc = "Standard Linux Telephony API Driver";
static char *config = "phone.conf";
/* Default context for dialtone mode */
static char context[AST_MAX_EXTENSION] = "default";
char *ignore_rcs_id_for_chan_ixj = ixjuser_h_rcsid;
/* Default language */
static char language[MAX_LANGUAGE] = "";
static int usecnt =0;
static int echocancel = AEC_OFF;
static int silencesupression = 0;
static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR;
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
/* Protect the interface list (of ixj_pvt's) */
/* Protect the interface list (of phone_pvt's) */
static pthread_mutex_t iflock = PTHREAD_MUTEX_INITIALIZER;
/* Protect the monitoring thread, so only one process can kill or start it, and not
@@ -68,7 +75,7 @@ static int restart_monitor(void);
#define MODE_DIALTONE 1
#define MODE_IMMEDIATE 2
static struct ixj_pvt {
static struct phone_pvt {
int fd; /* Raw file descriptor for this device */
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
int mode; /* Is this in the */
@@ -76,20 +83,22 @@ static struct ixj_pvt {
int lastinput; /* Last input format */
int ministate; /* Miniature state, for dialtone mode */
char dev[256]; /* Device name */
struct ixj_pvt *next; /* Next channel in list */
struct phone_pvt *next; /* Next channel in list */
struct ast_frame fr; /* Frame */
char offset[AST_FRIENDLY_OFFSET];
char buf[IXJ_MAX_BUF]; /* Static buffer for reading frames */
char buf[phone_MAX_BUF]; /* Static buffer for reading frames */
int obuflen;
int dialtone;
int silencesupression;
char context[AST_MAX_EXTENSION];
char obuf[IXJ_MAX_BUF * 2];
char obuf[phone_MAX_BUF * 2];
char ext[AST_MAX_EXTENSION];
char language[MAX_LANGUAGE];
} *iflist = NULL;
static int ixj_digit(struct ast_channel *ast, char digit)
static int phone_digit(struct ast_channel *ast, char digit)
{
struct ixj_pvt *p;
struct phone_pvt *p;
int outdigit;
p = ast->pvt->pvt;
switch(digit) {
@@ -115,57 +124,60 @@ static int ixj_digit(struct ast_channel *ast, char digit)
ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
return -1;
}
ioctl(p->fd, IXJCTL_PLAY_TONE, digit);
ioctl(p->fd, PHONE_PLAY_TONE, digit);
return 0;
}
static int ixj_call(struct ast_channel *ast, char *dest, int timeout)
static int phone_call(struct ast_channel *ast, char *dest, int timeout)
{
struct ixj_pvt *p;
struct phone_pvt *p;
p = ast->pvt->pvt;
if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "ixj_call called on %s, neither down nor reserved\n", ast->name);
ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name);
return -1;
}
/* When we call, it just works, really, there's no destination... Just
ring the phone and wait for someone to answer */
if (option_debug)
ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fd);
ioctl(p->fd, IXJCTL_RING_START);
ioctl(p->fd, PHONE_RING_START);
ast->state = AST_STATE_RINGING;
return 0;
}
static int ixj_hangup(struct ast_channel *ast)
static int phone_hangup(struct ast_channel *ast)
{
struct ixj_pvt *p;
struct phone_pvt *p;
p = ast->pvt->pvt;
if (option_debug)
ast_log(LOG_DEBUG, "ixj_hangup(%s)\n", ast->name);
ast_log(LOG_DEBUG, "phone_hangup(%s)\n", ast->name);
if (!ast->pvt->pvt) {
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
return 0;
}
/* XXX Is there anything we can do to really hang up except stop recording? */
ast->state = AST_STATE_DOWN;
if (ioctl(p->fd, IXJCTL_REC_STOP))
if (ioctl(p->fd, PHONE_REC_STOP))
ast_log(LOG_WARNING, "Failed to stop recording\n");
if (ioctl(p->fd, IXJCTL_PLAY_STOP))
if (ioctl(p->fd, PHONE_PLAY_STOP))
ast_log(LOG_WARNING, "Failed to stop playing\n");
if (ioctl(p->fd, IXJCTL_RING_STOP))
if (ioctl(p->fd, PHONE_RING_STOP))
ast_log(LOG_WARNING, "Failed to stop ringing\n");
if (ioctl(p->fd, IXJCTL_CPT_STOP))
if (ioctl(p->fd, PHONE_CPT_STOP))
ast_log(LOG_WARNING, "Failed to stop sounds\n");
/* If they're off hook, give a busy signal */
if (ioctl(p->fd, IXJCTL_HOOKSTATE))
ioctl(p->fd, IXJCTL_BUSY);
if (ioctl(p->fd, PHONE_HOOKSTATE)) {
if (option_debug)
ast_log(LOG_DEBUG, "Got hunghup, giving busy signal\n");
ioctl(p->fd, PHONE_BUSY);
}
p->lastformat = -1;
p->lastinput = -1;
p->ministate = 0;
p->obuflen = 0;
p->dialtone = 0;
memset(p->ext, 0, sizeof(p->ext));
((struct ixj_pvt *)(ast->pvt->pvt))->owner = NULL;
((struct phone_pvt *)(ast->pvt->pvt))->owner = NULL;
pthread_mutex_lock(&usecnt_lock);
usecnt--;
if (usecnt < 0)
@@ -180,27 +192,27 @@ static int ixj_hangup(struct ast_channel *ast)
return 0;
}
static int ixj_setup(struct ast_channel *ast)
static int phone_setup(struct ast_channel *ast)
{
struct ixj_pvt *p;
struct phone_pvt *p;
p = ast->pvt->pvt;
ioctl(p->fd, IXJCTL_CPT_STOP);
ioctl(p->fd, PHONE_CPT_STOP);
/* Nothing to answering really, just start recording */
if (ast->format & AST_FORMAT_G723_1) {
/* Prefer g723 */
ioctl(p->fd, IXJCTL_REC_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (p->lastinput != AST_FORMAT_G723_1) {
p->lastinput = AST_FORMAT_G723_1;
if (ioctl(p->fd, IXJCTL_REC_CODEC, G723_63)) {
if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
ast_log(LOG_WARNING, "Failed to set codec to g723.1\n");
return -1;
}
}
} else if (ast->format & AST_FORMAT_SLINEAR) {
ioctl(p->fd, IXJCTL_REC_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (p->lastinput != AST_FORMAT_SLINEAR) {
p->lastinput = AST_FORMAT_SLINEAR;
if (ioctl(p->fd, IXJCTL_REC_CODEC, LINEAR16)) {
if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
return -1;
}
@@ -209,24 +221,24 @@ static int ixj_setup(struct ast_channel *ast)
ast_log(LOG_WARNING, "Can't do format %d\n", ast->format);
return -1;
}
if (ioctl(p->fd, IXJCTL_REC_START)) {
if (ioctl(p->fd, PHONE_REC_START)) {
ast_log(LOG_WARNING, "Failed to start recording\n");
return -1;
}
return 0;
}
static int ixj_answer(struct ast_channel *ast)
static int phone_answer(struct ast_channel *ast)
{
ixj_setup(ast);
phone_setup(ast);
if (option_debug)
ast_log(LOG_DEBUG, "ixj_answer(%s)\n", ast->name);
ast_log(LOG_DEBUG, "phone_answer(%s)\n", ast->name);
ast->rings = 0;
ast->state = AST_STATE_UP;
return 0;
}
static char ixj_2digit(char c)
static char phone_2digit(char c)
{
if (c == 12)
return '#';
@@ -238,11 +250,11 @@ static char ixj_2digit(char c)
return '?';
}
static struct ast_frame *ixj_read(struct ast_channel *ast)
static struct ast_frame *phone_read(struct ast_channel *ast)
{
int res;
IXJ_EXCEPTION ixje;
struct ixj_pvt *p = ast->pvt->pvt;
union telephony_exception phonee;
struct phone_pvt *p = ast->pvt->pvt;
char digit;
/* Some nice norms */
@@ -253,16 +265,16 @@ static struct ast_frame *ixj_read(struct ast_channel *ast)
p->fr.offset = 0;
p->fr.mallocd=0;
ixje.bytes = ioctl(p->fd, IXJCTL_EXCEPTION);
if (ixje.bits.dtmf_ready) {
phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
if (phonee.bits.dtmf_ready) {
/* We've got a digit -- Just handle this nicely and easily */
digit = ioctl(p->fd, IXJCTL_GET_DTMF_ASCII);
digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII);
p->fr.subclass = digit;
p->fr.frametype = AST_FRAME_DTMF;
return &p->fr;
}
if (ixje.bits.hookstate) {
res = ioctl(p->fd, IXJCTL_HOOKSTATE);
if (phonee.bits.hookstate) {
res = ioctl(p->fd, PHONE_HOOKSTATE);
/* See if we've gone on hook, if so, notify by returning NULL */
if (!res)
return NULL;
@@ -271,23 +283,23 @@ static struct ast_frame *ixj_read(struct ast_channel *ast)
/* They've picked up the phone */
p->fr.frametype = AST_FRAME_CONTROL;
p->fr.subclass = AST_CONTROL_ANSWER;
ixj_setup(ast);
phone_setup(ast);
ast->state = AST_STATE_UP;
return &p->fr;
} else
ast_log(LOG_WARNING, "Got off hook in weird state\n");
ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->state);
}
}
#if 0
if (ixje.bits.pstn_ring)
if (phonee.bits.pstn_ring)
ast_verbose("Unit is ringing\n");
if (ixje.bits.caller_id) {
if (phonee.bits.caller_id) {
ast_verbose("We have caller ID: %s\n");
}
#endif
/* Try to read some data... */
CHECK_BLOCKING(ast);
res = read(p->fd, p->buf, IXJ_MAX_BUF);
res = read(p->fd, p->buf, phone_MAX_BUF);
ast->blocking = 0;
if (res < 0) {
#if 0
@@ -302,6 +314,17 @@ static struct ast_frame *ixj_read(struct ast_channel *ast)
return NULL;
}
p->fr.data = p->buf;
switch(p->buf[0] & 0x3) {
case '0':
case '1':
/* Normal */
break;
case '2':
case '3':
/* VAD/CNG, only send two words */
res = 4;
break;
}
p->fr.datalen = res;
p->fr.frametype = AST_FRAME_VOICE;
p->fr.subclass = p->lastinput;
@@ -309,7 +332,7 @@ static struct ast_frame *ixj_read(struct ast_channel *ast)
return &p->fr;
}
static int ixj_write_buf(struct ixj_pvt *p, char *buf, int len, int frlen)
static int phone_write_buf(struct phone_pvt *p, char *buf, int len, int frlen)
{
int res;
/* Store as much of the buffer as we can, then write fixed frames */
@@ -342,14 +365,15 @@ static int ixj_write_buf(struct ixj_pvt *p, char *buf, int len, int frlen)
return len;
}
static int ixj_write(struct ast_channel *ast, struct ast_frame *frame)
static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
{
struct ixj_pvt *p = ast->pvt->pvt;
struct phone_pvt *p = ast->pvt->pvt;
int res;
int maxfr=0;
char *pos;
int sofar;
int expected;
char tmpbuf[4];
/* Write a frame of (presumably voice) data */
if (frame->frametype != AST_FRAME_VOICE) {
ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
@@ -361,14 +385,25 @@ static int ixj_write(struct ast_channel *ast, struct ast_frame *frame)
ast_frfree(frame);
return -1;
}
/* If we're not in up mode, go into up mode now */
if (ast->state != AST_STATE_UP) {
ast->state = AST_STATE_UP;
phone_setup(ast);
}
if (frame->subclass == AST_FORMAT_G723_1) {
if (p->lastformat != AST_FORMAT_G723_1) {
ioctl(p->fd, IXJCTL_PLAY_STOP);
if (ioctl(p->fd, IXJCTL_PLAY_CODEC, G723_63)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {
ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
return -1;
}
if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");
return -1;
}
p->lastformat = AST_FORMAT_G723_1;
p->lastinput = AST_FORMAT_G723_1;
/* Reset output buffer */
p->obuflen = 0;
}
@@ -379,18 +414,30 @@ static int ixj_write(struct ast_channel *ast, struct ast_frame *frame)
maxfr = 24;
} else if (frame->subclass == AST_FORMAT_SLINEAR) {
if (p->lastformat != AST_FORMAT_SLINEAR) {
ioctl(p->fd, IXJCTL_PLAY_STOP);
if (ioctl(p->fd, IXJCTL_PLAY_CODEC, LINEAR16)) {
ioctl(p->fd, PHONE_PLAY_STOP);
ioctl(p->fd, PHONE_REC_STOP);
if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {
ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
return -1;
}
if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");
return -1;
}
p->lastformat = AST_FORMAT_SLINEAR;
p->lastinput = AST_FORMAT_SLINEAR;
/* Reset output buffer */
p->obuflen = 0;
}
maxfr = 480;
}
if (ioctl(p->fd, IXJCTL_PLAY_START)) {
ioctl(p->fd, PHONE_REC_DEPTH, 3);
ioctl(p->fd, PHONE_PLAY_DEPTH, 3);
if (ioctl(p->fd, PHONE_PLAY_START)) {
ast_log(LOG_WARNING, "Failed to start playback\n");
return -1;
}
if (ioctl(p->fd, PHONE_REC_START)) {
ast_log(LOG_WARNING, "Failed to start recording\n");
return -1;
}
@@ -402,55 +449,67 @@ static int ixj_write(struct ast_channel *ast, struct ast_frame *frame)
expected = frame->datalen - sofar;
if (maxfr < expected)
expected = maxfr;
/* XXX Internet Phone Jack does not handle the 4-byte VAD frame properly! XXX */
if (frame->datalen != 4) {
res = ixj_write_buf(p, pos, expected, maxfr);
if (res != expected) {
if (res < 0)
ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
else
ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
return -1;
/* XXX Internet Phone Jack does not handle the 4-byte VAD frame properly! XXX
we have to pad it to 24 bytes still. */
if (frame->datalen == 4) {
if (p->silencesupression) {
memset(tmpbuf + 4, 0, sizeof(tmpbuf) - 4);
memcpy(tmpbuf, frame->data, 4);
expected = 24;
res = phone_write_buf(p, tmpbuf, expected, maxfr);
}
sofar += res;
pos += res;
} else
sofar += 4;
res = 4;
expected=4;
} else {
res = phone_write_buf(p, pos, expected, maxfr);
}
if (res != expected) {
if (res < 0)
ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
else
ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
return -1;
}
sofar += res;
pos += res;
}
return 0;
}
static struct ast_channel *ixj_new(struct ixj_pvt *i, int state)
static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *context)
{
struct ast_channel *tmp;
tmp = ast_channel_alloc();
if (tmp) {
snprintf(tmp->name, sizeof(tmp->name), "PhoneJack/%s", i->dev + 5);
snprintf(tmp->name, sizeof(tmp->name), "Phone/%s", i->dev + 5);
tmp->type = type;
tmp->fd = i->fd;
/* XXX Switching formats silently causes kernel panics XXX */
tmp->format = AST_FORMAT_G723_1 /* | AST_FORMAT_SLINEAR */;
tmp->format = prefformat;
tmp->state = state;
if (state == AST_STATE_RING)
tmp->rings = 1;
tmp->pvt->pvt = i;
tmp->pvt->send_digit = ixj_digit;
tmp->pvt->call = ixj_call;
tmp->pvt->hangup = ixj_hangup;
tmp->pvt->answer = ixj_answer;
tmp->pvt->read = ixj_read;
tmp->pvt->write = ixj_write;
strncpy(tmp->context, i->context, sizeof(tmp->context));
tmp->pvt->send_digit = phone_digit;
tmp->pvt->call = phone_call;
tmp->pvt->hangup = phone_hangup;
tmp->pvt->answer = phone_answer;
tmp->pvt->read = phone_read;
tmp->pvt->write = phone_write;
strncpy(tmp->context, context, sizeof(tmp->context));
if (strlen(i->ext))
strncpy(tmp->exten, i->ext, sizeof(tmp->exten));
if (strlen(i->language))
strncpy(tmp->language, i->language, sizeof(tmp->language));
i->owner = tmp;
pthread_mutex_lock(&usecnt_lock);
usecnt++;
pthread_mutex_unlock(&usecnt_lock);
ast_update_use_count();
if (state != AST_STATE_DOWN) {
if (state == AST_STATE_RING)
ioctl(tmp->fd, IXJCTL_RINGBACK);
if (state == AST_STATE_RING) {
ioctl(tmp->fd, PHONE_RINGBACK);
}
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
ast_hangup(tmp);
@@ -461,7 +520,7 @@ static struct ast_channel *ixj_new(struct ixj_pvt *i, int state)
return tmp;
}
static void ixj_mini_packet(struct ixj_pvt *i)
static void phone_mini_packet(struct phone_pvt *i)
{
int res;
char buf[1024];
@@ -473,75 +532,77 @@ static void ixj_mini_packet(struct ixj_pvt *i)
}
}
static void ixj_check_exception(struct ixj_pvt *i)
static void phone_check_exception(struct phone_pvt *i)
{
int offhook=0;
char digit[2] = {0 , 0};
IXJ_EXCEPTION ixje;
union telephony_exception phonee;
/* XXX Do something XXX */
#if 0
ast_log(LOG_DEBUG, "Exception!\n");
#endif
ixje.bytes = ioctl(i->fd, IXJCTL_EXCEPTION);
if (ixje.bits.dtmf_ready) {
digit[0] = ioctl(i->fd, IXJCTL_GET_DTMF_ASCII);
phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);
if (phonee.bits.dtmf_ready) {
digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);
if (i->mode == MODE_DIALTONE) {
ioctl(i->fd, IXJCTL_PLAY_STOP);
ioctl(i->fd, IXJCTL_REC_STOP);
ioctl(i->fd, IXJCTL_CPT_STOP);
ioctl(i->fd, PHONE_PLAY_STOP);
ioctl(i->fd, PHONE_REC_STOP);
ioctl(i->fd, PHONE_CPT_STOP);
i->dialtone = 0;
if (strlen(i->ext) < AST_MAX_EXTENSION - 1)
strcat(i->ext, digit);
if (ast_exists_extension(NULL, i->context, i->ext, 1)) {
/* It's a valid extension in its context, get moving! */
ixj_new(i, AST_STATE_UP);
phone_new(i, AST_STATE_RING, i->context);
/* No need to restart monitor, we are the monitor */
if (i->owner) {
pthread_mutex_lock(&usecnt_lock);
usecnt--;
pthread_mutex_unlock(&usecnt_lock);
ast_update_use_count();
ixj_setup(i->owner);
}
} else if (ast_exists_extension(NULL, "default", i->ext, 1)) {
/* Check the default, too... */
/* XXX This should probably be justified better XXX */
strncpy(i->context, "default", sizeof(i->context));
ixj_new(i, AST_STATE_UP);
if (i->owner) {
pthread_mutex_lock(&usecnt_lock);
usecnt--;
pthread_mutex_unlock(&usecnt_lock);
ast_update_use_count();
ixj_setup(i->owner);
} else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1)) {
/* There is nothing in the specified extension that can match anymore.
Try the default */
if (ast_exists_extension(NULL, "default", i->ext, 1)) {
/* Check the default, too... */
phone_new(i, AST_STATE_RING, "default");
if (i->owner) {
pthread_mutex_lock(&usecnt_lock);
usecnt--;
pthread_mutex_unlock(&usecnt_lock);
ast_update_use_count();
}
/* XXX This should probably be justified better XXX */
} else if (!ast_canmatch_extension(NULL, "default", i->ext, 1)) {
/* It's not a valid extension, give a busy signal */
if (option_debug)
ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context);
ioctl(i->fd, PHONE_BUSY);
}
} else if ((strlen(i->ext) >= ast_pbx_longest_extension(i->context)) &&
(strlen(i->ext) >= ast_pbx_longest_extension("default"))) {
if (option_debug)
ast_log(LOG_DEBUG, "%s is too long\n", i->ext);
/* It's not a valid extension, give a busy signal */
ioctl(i->fd, IXJCTL_BUSY);
}
#if 0
ast_verbose("Extension is %s\n", i->ext);
#endif
}
}
if (ixje.bits.hookstate) {
offhook = ioctl(i->fd, IXJCTL_HOOKSTATE);
if (phonee.bits.hookstate) {
offhook = ioctl(i->fd, PHONE_HOOKSTATE);
if (offhook) {
if (i->mode == MODE_IMMEDIATE) {
ixj_new(i, AST_STATE_RING);
phone_new(i, AST_STATE_RING, i->context);
} else if (i->mode == MODE_DIALTONE) {
pthread_mutex_lock(&usecnt_lock);
usecnt++;
pthread_mutex_unlock(&usecnt_lock);
ast_update_use_count();
/* Reset the extension */
i->ext[0] = '\0';
/* Play the dialtone */
i->dialtone++;
ioctl(i->fd, IXJCTL_PLAY_STOP);
ioctl(i->fd, IXJCTL_PLAY_CODEC, ULAW);
ioctl(i->fd, IXJCTL_PLAY_START);
ioctl(i->fd, PHONE_PLAY_STOP);
ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);
ioctl(i->fd, PHONE_PLAY_START);
}
} else {
if (i->dialtone) {
@@ -551,15 +612,15 @@ static void ixj_check_exception(struct ixj_pvt *i)
ast_update_use_count();
}
memset(i->ext, 0, sizeof(i->ext));
ioctl(i->fd, IXJCTL_CPT_STOP);
ioctl(i->fd, IXJCTL_PLAY_STOP);
ioctl(i->fd, IXJCTL_REC_STOP);
ioctl(i->fd, PHONE_CPT_STOP);
ioctl(i->fd, PHONE_PLAY_STOP);
ioctl(i->fd, PHONE_REC_STOP);
i->dialtone = 0;
}
}
if (ixje.bits.pstn_ring)
if (phonee.bits.pstn_ring)
ast_verbose("Unit is ringing\n");
if (ixje.bits.caller_id)
if (phonee.bits.caller_id)
ast_verbose("We have caller ID\n");
@@ -569,7 +630,7 @@ static void *do_monitor(void *data)
{
fd_set rfds, efds;
int n, res;
struct ixj_pvt *i;
struct phone_pvt *i;
int tonepos = 0;
/* The tone we're playing this round */
struct timeval tv = {0,0};
@@ -595,7 +656,7 @@ static void *do_monitor(void *data)
return NULL;
}
/* Build the stuff we're going to select on, that is the socket of every
ixj_pvt that does not have an associated owner channel */
phone_pvt that does not have an associated owner channel */
n = -1;
FD_ZERO(&rfds);
FD_ZERO(&efds);
@@ -668,14 +729,14 @@ static void *do_monitor(void *data)
ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->fd, i->dev);
continue;
}
ixj_mini_packet(i);
phone_mini_packet(i);
}
if (FD_ISSET(i->fd, &efds)) {
if (i->owner) {
ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->fd, i->dev);
continue;
}
ixj_check_exception(i);
phone_check_exception(i);
}
i=i->next;
}
@@ -716,15 +777,15 @@ static int restart_monitor()
return 0;
}
static struct ixj_pvt *mkif(char *iface, int mode)
static struct phone_pvt *mkif(char *iface, int mode)
{
/* Make a ixj_pvt structure for this interface */
struct ixj_pvt *tmp;
/* Make a phone_pvt structure for this interface */
struct phone_pvt *tmp;
#if 0
int flags;
#endif
tmp = malloc(sizeof(struct ixj_pvt));
tmp = malloc(sizeof(struct phone_pvt));
if (tmp) {
tmp->fd = open(iface, O_RDWR);
if (tmp->fd < 0) {
@@ -732,10 +793,17 @@ static struct ixj_pvt *mkif(char *iface, int mode)
free(tmp);
return NULL;
}
ioctl(tmp->fd, IXJCTL_PLAY_STOP);
ioctl(tmp->fd, IXJCTL_REC_STOP);
ioctl(tmp->fd, IXJCTL_RING_STOP);
ioctl(tmp->fd, IXJCTL_CPT_STOP);
ioctl(tmp->fd, PHONE_PLAY_STOP);
ioctl(tmp->fd, PHONE_REC_STOP);
ioctl(tmp->fd, PHONE_RING_STOP);
ioctl(tmp->fd, PHONE_CPT_STOP);
if (echocancel != AEC_OFF)
ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);
if (silencesupression)
tmp->silencesupression = 1;
#ifdef PHONE_VAD
ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);
#endif
tmp->mode = mode;
#if 0
flags = fcntl(tmp->fd, F_GETFL);
@@ -746,6 +814,7 @@ static struct ixj_pvt *mkif(char *iface, int mode)
tmp->lastinput = -1;
tmp->ministate = 0;
memset(tmp->ext, 0, sizeof(tmp->ext));
strncpy(tmp->language, language, sizeof(tmp->language));
strncpy(tmp->dev, iface, sizeof(tmp->dev));
strncpy(tmp->context, context, sizeof(tmp->context));
tmp->next = NULL;
@@ -755,10 +824,10 @@ static struct ixj_pvt *mkif(char *iface, int mode)
return tmp;
}
static struct ast_channel *ixj_request(char *type, int format, void *data)
static struct ast_channel *phone_request(char *type, int format, void *data)
{
int oldformat;
struct ixj_pvt *p;
struct phone_pvt *p;
struct ast_channel *tmp = NULL;
char *name = data;
@@ -777,7 +846,7 @@ static struct ast_channel *ixj_request(char *type, int format, void *data)
while(p) {
if (!strcmp(name, p->dev + 5)) {
if (!p->owner) {
tmp = ixj_new(p, AST_STATE_DOWN);
tmp = phone_new(p, AST_STATE_DOWN, p->context);
break;
}
}
@@ -792,7 +861,7 @@ int load_module()
{
struct ast_config *cfg;
struct ast_variable *v;
struct ixj_pvt *tmp;
struct phone_pvt *tmp;
int mode = MODE_IMMEDIATE;
cfg = ast_load(config);
@@ -822,6 +891,10 @@ int load_module()
unload_module();
return -1;
}
} else if (!strcasecmp(v->name, "silencesupression")) {
silencesupression = ast_true(v->value);
} else if (!strcasecmp(v->name, "language")) {
strncpy(language, v->value, sizeof(language));
} else if (!strcasecmp(v->name, "mode")) {
if (!strncasecmp(v->value, "di", 2))
mode = MODE_DIALTONE;
@@ -831,12 +904,30 @@ int load_module()
ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
} else if (!strcasecmp(v->name, "context")) {
strncpy(context, v->value, sizeof(context));
} else if (!strcasecmp(v->name, "format")) {
if (!strcasecmp(v->value, "g723.1")) {
prefformat = AST_FORMAT_G723_1;
} else if (!strcasecmp(v->value, "slinear")) {
prefformat = AST_FORMAT_SLINEAR;
} else
ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);
} else if (!strcasecmp(v->name, "echocancel")) {
if (!strcasecmp(v->value, "off")) {
echocancel = AEC_OFF;
} else if (!strcasecmp(v->value, "low")) {
echocancel = AEC_LOW;
} else if (!strcasecmp(v->value, "medium")) {
echocancel = AEC_MED;
} else if (!strcasecmp(v->value, "high")) {
echocancel = AEC_HIGH;
} else
ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);
}
v = v->next;
}
pthread_mutex_unlock(&iflock);
/* Make sure we can register our Adtranixj channel type */
if (ast_channel_register(type, tdesc, AST_FORMAT_G723_1, ixj_request)) {
/* Make sure we can register our Adtranphone channel type */
if (ast_channel_register(type, tdesc, AST_FORMAT_G723_1, phone_request)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
ast_destroy(cfg);
unload_module();
@@ -852,7 +943,7 @@ int load_module()
int unload_module()
{
struct ixj_pvt *p, *pl;
struct phone_pvt *p, *pl;
/* First, take us out of the channel loop */
ast_channel_unregister(type);
if (!pthread_mutex_lock(&iflock)) {

104
channels/chan_vofr.c Executable file → Normal file
View File

@@ -28,8 +28,15 @@
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#ifndef OLD_SANGOMA_API
#include <linux/if_wanpipe.h>
#include <linux/wanpipe.h>
#endif
#include <sys/signal.h>
#include "adtranvofr.h"
/* #define VOFRDUMPER */
#define G723_MAX_BUF 2048
#define FR_API_MESS 16
@@ -41,6 +48,8 @@ static char *config = "adtranvofr.conf";
static char context[AST_MAX_EXTENSION] = "default";
static char language[MAX_LANGUAGE] = "";
static int usecnt =0;
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -53,7 +62,7 @@ static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER;
/* This is the thread for the monitor which checks for input on the channels
which are not currently in use. */
static pthread_t monitor_thread = -1;
static pthread_t monitor_thread = 0;
static int restart_monitor(void);
@@ -62,7 +71,11 @@ static int restart_monitor(void);
static struct vofr_pvt {
int s; /* Raw socket for this DLCI */
#ifdef OLD_SANGOMA_API
struct sockaddr_pkt sa; /* Sockaddr needed for sending, also has iface name */
#else
struct wan_sockaddr_ll sa; /* Wanpipe sockaddr */
#endif
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
int outgoing; /* Does this channel support outgoing calls? */
struct vofr_pvt *next; /* Next channel in list */
@@ -74,6 +87,8 @@ static struct vofr_pvt {
char buf[G723_MAX_BUF]; /* Static buffer for reading frames */
char obuf[G723_MAX_BUF]; /* Output buffer */
char context[AST_MAX_EXTENSION];
char language[MAX_LANGUAGE];
int ringgothangup; /* Have we received exactly one hangup after a ring */
} *iflist = NULL;
#ifdef VOFRDUMPER
@@ -240,7 +255,11 @@ static void vofr_dump_packet(struct vofr_hdr *vh, int len)
static int vofr_xmit(struct vofr_pvt *p, char *data, int len)
{
int res;
#ifdef OLD_SANGOMA_API
res=sendto(p->s, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_pkt));
#else
res=sendto(p->s, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct wan_sockaddr_ll));
#endif
if (res != len) {
ast_log(LOG_WARNING, "vofr_xmit returned %d\n", res);
}
@@ -433,6 +452,7 @@ static int vofr_hangup(struct ast_channel *ast)
}
ast->state = AST_STATE_DOWN;
((struct vofr_pvt *)(ast->pvt->pvt))->owner = NULL;
((struct vofr_pvt *)(ast->pvt->pvt))->ringgothangup = 0;
pthread_mutex_lock(&usecnt_lock);
usecnt--;
if (usecnt < 0)
@@ -464,6 +484,9 @@ static int vofr_answer(struct ast_channel *ast)
cnt = ast_waitfor(ast, cnt);
if (cnt > 0) {
res = read(ast->fd, buf, sizeof(buf));
#ifdef VOFRDUMPER
vofr_dump_packet((void *)(buf +FR_API_MESS), res - FR_API_MESS);
#endif
res -= FR_API_MESS;
if (res < 0)
ast_log(LOG_WARNING, "Warning: read failed (%s) on %s\n", strerror(errno), ast->name);
@@ -530,6 +553,9 @@ static struct ast_frame *vofr_read(struct ast_channel *ast)
CHECK_BLOCKING(ast);
res = read(p->s, ((char *)vh) - FR_API_MESS,
G723_MAX_BUF - AST_FRIENDLY_OFFSET - sizeof(struct ast_frame) + sizeof(struct vofr_hdr) + FR_API_MESS);
#ifdef VOFRDUMPER
vofr_dump_packet((void *)(vh), res);
#endif
ast->blocking = 0;
res -= FR_API_MESS;
if (res < sizeof(struct vofr_hdr *)) {
@@ -551,15 +577,17 @@ static struct ast_frame *vofr_read(struct ast_channel *ast)
switch(vh->data[0]) {
case VOFR_SIGNAL_ON_HOOK:
/* Hang up this line */
if (ast->state == AST_STATE_UP)
if ((ast->state == AST_STATE_UP) || (p->ringgothangup)) {
return NULL;
else {
} else {
fr->frametype = AST_FRAME_NULL;
fr->subclass = 0;
break;
p->ringgothangup=1;
}
break;
case VOFR_SIGNAL_RING:
ast->rings++;
p->ringgothangup = 0;
break;
case VOFR_SIGNAL_UNKNOWN:
switch(vh->data[1]) {
@@ -744,7 +772,11 @@ static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
struct ast_channel *tmp;
tmp = ast_channel_alloc();
if (tmp) {
#ifdef OLD_SANGOMA_API
snprintf(tmp->name, sizeof(tmp->name), "AdtranVoFR/%s", i->sa.spkt_device);
#else
snprintf(tmp->name, sizeof(tmp->name), "AdtranVoFR/%s", i->sa.sll_device);
#endif
tmp->type = type;
tmp->fd = i->s;
/* Adtran VoFR supports only G723.1 format data. G711 (ulaw) would be nice too */
@@ -759,6 +791,8 @@ static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
tmp->pvt->answer = vofr_answer;
tmp->pvt->read = vofr_read;
tmp->pvt->write = vofr_write;
if (strlen(i->language))
strncpy(tmp->language, i->language, sizeof(tmp->language));
i->owner = tmp;
pthread_mutex_lock(&usecnt_lock);
usecnt++;
@@ -769,6 +803,7 @@ static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
ast_hangup(tmp);
tmp = NULL;
}
}
} else
@@ -786,9 +821,10 @@ static int vofr_mini_packet(struct vofr_pvt *i, struct vofr_hdr *pkt, int len)
switch(pkt->data[0]) {
case VOFR_SIGNAL_RING:
/* If we get a RING, we definitely want to start a new thread */
if (!i->owner)
if (!i->owner) {
i->ringgothangup = 0;
vofr_new(i, AST_STATE_RING);
else
} else
ast_log(LOG_WARNING, "Got a ring, but there's an owner?\n");
break;
case VOFR_SIGNAL_OFF_HOOK:
@@ -839,10 +875,12 @@ static void *do_monitor(void *data)
/* This thread monitors all the frame relay interfaces which are not yet in use
(and thus do not have a separate thread) indefinitely */
/* From here on out, we die whenever asked */
#if 0
if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
return NULL;
}
#endif
for(;;) {
/* Don't let anybody kill us right away. Nobody should lock the interface list
and wait for the monitor list, but the other way around is okay. */
@@ -863,7 +901,11 @@ static void *do_monitor(void *data)
i = iflist;
while(i) {
if (FD_ISSET(i->s, &rfds))
#ifdef OLD_SANGOMA_API
ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->s, i->sa.spkt_device);
#else
ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->s, i->sa.sll_device);
#endif
if (!i->owner) {
/* This needs to be watched, as it lacks an owner */
FD_SET(i->s, &rfds);
@@ -877,11 +919,14 @@ static void *do_monitor(void *data)
/* And from now on, we're okay to be killed, so release the monitor lock as well */
pthread_mutex_unlock(&monlock);
pthread_testcancel();
/* Wait indefinitely for something to happen */
res = select(n + 1, &rfds, NULL, NULL, NULL);
pthread_testcancel();
/* Okay, select has finished. Let's see what happened. */
if (res < 0) {
ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
if ((errno != EAGAIN) && (errno != EINTR))
ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
continue;
}
/* Alright, lock the interface list again, and let's look and see what has
@@ -894,7 +939,11 @@ static void *do_monitor(void *data)
while(i) {
if (FD_ISSET(i->s, &rfds)) {
if (i->owner) {
#ifdef OLD_SANGOMA_API
ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->s, i->sa.spkt_device);
#else
ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->s, i->sa.sll_device);
#endif
continue;
}
res = read(i->s, i->buf, sizeof(i->buf));
@@ -927,12 +976,16 @@ static int restart_monitor(void)
ast_log(LOG_WARNING, "Cannot kill myself\n");
return -1;
}
if (monitor_thread != -1) {
if (monitor_thread) {
#if 0
pthread_cancel(monitor_thread);
#endif
pthread_kill(monitor_thread, SIGURG);
#if 0
pthread_join(monitor_thread, NULL);
#endif
}
if (!monitor_thread)
/* Start a new monitor */
if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
pthread_mutex_unlock(&monlock);
@@ -953,22 +1006,44 @@ static struct vofr_pvt *mkif(char *type, char *iface)
if (tmp) {
/* Allocate a packet socket */
#ifdef OLD_SANGOMA_API
tmp->s = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL));
#else
/* Why the HELL does Sangoma change their API every damn time
they make a new driver release?!?!?! Leave it the hell
alone this time. */
tmp->s = socket(AF_WANPIPE, SOCK_RAW, 0);
#endif
if (tmp->s < 0) {
ast_log(LOG_ERROR, "Unable to create socket: %s\n", strerror(errno));
free(tmp);
return NULL;
}
#ifdef OLD_SANGOMA_API
/* Prepare sockaddr for binding */
memset(&tmp->sa, 0, sizeof(tmp->sa));
strncpy(tmp->sa.spkt_device, iface, sizeof(tmp->sa.spkt_device));
tmp->sa.spkt_protocol = htons(0x16);
tmp->sa.spkt_family = AF_PACKET;
/* Bind socket to specific interface */
if (bind(tmp->s, (struct sockaddr *)&tmp->sa, sizeof(struct sockaddr))) {
#else
/* Prepare sockaddr for binding */
memset(&tmp->sa, 0, sizeof(tmp->sa));
tmp->sa.sll_family = AF_WANPIPE;
tmp->sa.sll_protocol = htons(ETH_P_IP);
strncpy(tmp->sa.sll_device, iface, sizeof(tmp->sa.sll_device));
strncpy(tmp->sa.sll_card, "wanpipe1", sizeof(tmp->sa.sll_card));
tmp->sa.sll_ifindex = 0;
if (bind(tmp->s, (struct sockaddr *)&tmp->sa, sizeof(struct wan_sockaddr_ll))) {
#endif
/* Bind socket to specific interface */
#ifdef OLD_SANGOMA_API
ast_log(LOG_ERROR, "Unable to bind to '%s': %s\n", tmp->sa.spkt_device,
#else
ast_log(LOG_ERROR, "Unable to bind to '%s': %s\n", tmp->sa.sll_device,
#endif
strerror(errno));
free(tmp);
return NULL;
@@ -986,6 +1061,8 @@ static struct vofr_pvt *mkif(char *type, char *iface)
tmp->dlcil = 0;
tmp->dlcih = 0;
tmp->cid = 1;
tmp->ringgothangup = 0;
strncpy(tmp->language, language, sizeof(tmp->language));
strncpy(tmp->context, context, sizeof(tmp->context));
/* User terminations are game for outgoing connections */
if (!strcasecmp(type, "user"))
@@ -1067,6 +1144,8 @@ int load_module()
}
} else if (!strcasecmp(v->name, "context")) {
strncpy(context, v->value, sizeof(context));
} else if (!strcasecmp(v->name, "language")) {
strncpy(language, v->value, sizeof(language));
}
v = v->next;
}
@@ -1084,8 +1163,6 @@ int load_module()
return 0;
}
int unload_module()
{
struct vofr_pvt *p, *pl;
@@ -1106,8 +1183,9 @@ int unload_module()
return -1;
}
if (!pthread_mutex_lock(&monlock)) {
if (monitor_thread > -1) {
if (monitor_thread) {
pthread_cancel(monitor_thread);
pthread_kill(monitor_thread, SIGURG);
pthread_join(monitor_thread, NULL);
}
monitor_thread = -2;

64
channels/iax.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Implementation of Inter-Asterisk eXchange
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#ifndef _ASTERISK_IAX_H
#define _ASTERISK_IAX_H
/* Max version of IAX protocol we support */
#define AST_IAX_PROTO_VERSION 1
#define AST_IAX_MAX_CALLS 32768
#define AST_FLAG_FULL 0x8000
#define AST_FLAG_SC_LOG 0x80
#define AST_MAX_SHIFT 0x1F
/* Subclass for AST_FRAME_IAX */
#define AST_IAX_COMMAND_NEW 1
#define AST_IAX_COMMAND_PING 2
#define AST_IAX_COMMAND_PONG 3
#define AST_IAX_COMMAND_ACK 4
#define AST_IAX_COMMAND_HANGUP 5
#define AST_IAX_COMMAND_REJECT 6
#define AST_IAX_COMMAND_ACCEPT 7
#define AST_IAX_COMMAND_AUTHREQ 8
#define AST_IAX_COMMAND_AUTHREP 9
#define AST_IAX_COMMAND_INVAL 10
#define AST_IAX_COMMAND_LAGRQ 11
#define AST_IAX_COMMAND_LAGRP 12
#define AST_DEFAULT_IAX_PORTNO 5036
/* Full frames are always delivered reliably */
struct ast_iax_full_hdr {
short callno; /* Source call number -- high bit must be 1 */
short dcallno; /* Destination call number */
unsigned int ts; /* 32-bit timestamp in milliseconds */
unsigned short seqno; /* Packet number */
char type; /* Frame type */
unsigned char csub; /* Compressed subclass */
char data[0];
};
/* Mini header is used only for voice frames -- delivered unreliably */
struct ast_iax_mini_hdr {
short callno; /* Source call number -- high bit must be 0 */
unsigned short ts; /* 16-bit Timestamp (high 32 bits from last ast_iax_full_hdr) */
/* Frametype implicitly VOICE_FRAME */
/* subclass implicit from last ast_iax_full_hdr */
char data[0];
};
#endif

4
channels/ixjuser.h Executable file → Normal file
View File

@@ -1,8 +1,8 @@
/******************************************************************************
$Id$
$Log$
Revision 1.15 1999/12/01 05:25:58 markster
Version 0.3.0 from FTP
Revision 1.4 1999/12/01 05:25:58 markster
Version 0.1.3 from FTP
Revision 1.1 1999/12/01 05:25:58 markster
Start on the Internet Phone Jack channel

64
cli.c Executable file → Normal file
View File

@@ -233,11 +233,11 @@ static int handle_help(int fd, int argc, char *argv[]);
static struct ast_cli_entry builtins[] = {
/* Keep alphabetized */
{ { "show" , "channels", NULL }, handle_chanlist, "Display information on channels", chanlist_help },
{ { "help", NULL }, handle_help, "Display help list, or specific help on a command", help_help },
{ { "load", NULL }, handle_load, "Load a dynamic module by name", load_help, complete_fn },
{ { "show", "modules", NULL }, handle_modlist, "List modules and info", modlist_help },
{ { "show", "channel", NULL }, handle_showchan, "Display information on a specific channel", showchan_help, complete_ch },
{ { "show", "channels", NULL }, handle_chanlist, "Display information on channels", chanlist_help },
{ { "show", "modules", NULL }, handle_modlist, "List modules and info", modlist_help },
{ { "unload", NULL }, handle_unload, "Unload a dynamic module by name", unload_help, complete_fn },
{ { NULL }, NULL, NULL, NULL }
};
@@ -271,7 +271,7 @@ static struct ast_cli_entry *find_cli(char *cmds[], int exact)
}
for (e=helpers;e;e=e->next) {
match = 1;
for (y=0;match && e->cmda[y]; y++) {
for (y=0;match && cmds[y]; y++) {
if (!e->cmda[y] && !exact)
break;
if (!e->cmda[y] || strcasecmp(e->cmda[y], cmds[y]))
@@ -297,6 +297,16 @@ static void join(char *s, int len, char *w[])
}
}
static void join2(char *s, int len, char *w[])
{
int x;
/* Join words into a string */
strcpy(s, "");
for (x=0;w[x];x++) {
strncat(s, w[x], len - strlen(s));
}
}
static char *find_best(char *argv[])
{
static char cmdline[80];
@@ -314,12 +324,35 @@ static char *find_best(char *argv[])
return cmdline;
}
int ast_cli_unregister(struct ast_cli_entry *e)
{
struct ast_cli_entry *cur, *l=NULL;
pthread_mutex_lock(&clilock);
cur = helpers;
while(cur) {
if (e == cur) {
/* Rewrite */
if (l)
l->next = e->next;
else
helpers = e->next;
e->next = NULL;
break;
}
l = cur;
cur = cur->next;
}
pthread_mutex_unlock(&clilock);
return 0;
}
int ast_cli_register(struct ast_cli_entry *e)
{
struct ast_cli_entry *cur, *l=NULL;
char fulle[80], fulltst[80];
static int len;
pthread_mutex_lock(&clilock);
join(fulle, sizeof(fulle), e->cmda);
join2(fulle, sizeof(fulle), e->cmda);
if (find_cli(e->cmda, -1)) {
ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle);
pthread_mutex_unlock(&clilock);
@@ -327,11 +360,18 @@ int ast_cli_register(struct ast_cli_entry *e)
}
cur = helpers;
while(cur) {
join(fulltst, sizeof(fulltst), cur->cmda);
if (strcmp(fulle, fulltst) > 0) {
/* Put it here */
e->next = cur->next;
cur->next = e;
join2(fulltst, sizeof(fulltst), cur->cmda);
len = strlen(fulltst);
if (strlen(fulle) < len)
len = strlen(fulle);
if (strncasecmp(fulle, fulltst, len) < 0) {
if (l) {
e->next = l->next;
l->next = e;
} else {
e->next = helpers;
helpers = e;
}
break;
}
l = cur;
@@ -364,7 +404,7 @@ static int help_workhorse(int fd, char *match[])
join(fullcmd2, sizeof(fullcmd2), e2->cmda);
if (e1->cmda[0])
join(fullcmd1, sizeof(fullcmd1), e1->cmda);
if (!e1->cmda ||
if (!e1->cmda[0] ||
(e2 && (strcmp(fullcmd2, fullcmd1) < 0))) {
/* Use e2 */
e = e2;
@@ -382,7 +422,7 @@ static int help_workhorse(int fd, char *match[])
continue;
}
}
ast_cli(fd, "%15s %s\n", fullcmd, e->summary);
ast_cli(fd, "%20.20s %s\n", fullcmd, e->summary);
}
return 0;
}
@@ -560,7 +600,7 @@ int ast_cli_command(int fd, char *s)
default:
}
} else
ast_cli(fd, "No such command '%s'\n", find_best(argv));
ast_cli(fd, "No such command '%s' (type 'help' for help)\n", find_best(argv));
pthread_mutex_unlock(&clilock);
}
free(dup);

12
codecs/Makefile Executable file → Normal file
View File

@@ -26,8 +26,9 @@ LIBG723=g723.1/libg723.a
LIBG723B=g723.1b/libg723b.a
LIBGSM=gsm/lib/libgsm.a
LIBMP3=mp3/libmp3.a
LIBLPC10=lpc10/liblpc10.a
CODECS+=$(MODG723) codec_gsm.so codec_mp3_d.so
CODECS+=$(MODG723) codec_gsm.so codec_mp3_d.so codec_lpc10.so
all: $(CODECS)
@@ -37,6 +38,7 @@ clean:
! [ -d g723.1b ] || make -C g723.1b clean
make -C gsm clean
make -C mp3 clean
make -C lpc10 clean
$(LIBG723):
make -C g723.1 all
@@ -50,11 +52,14 @@ $(LIBG723B):
$(LIBMP3):
make -C mp3 all
$(LIBLPC10):
make -C lpc10 all
codec_g723_1.so : codec_g723_1.o $(LIBG723)
$(CC) -shared -Xlinker -x -o $@ $< $(LIBG723)
codec_g723_1b.o : codec_g723_1.c
$(CC) -c -o $@ $(CFLAGS) -DANNEX_B $<
$(CC) -c -o $@ $(CFLAGS) -DANNEX_B -Dsingle $<
codec_g723_1b.so : codec_g723_1b.o $(LIBG723B)
$(CC) -shared -Xlinker -x -o $@ $< $(LIBG723B) -lm
@@ -62,6 +67,9 @@ codec_g723_1b.so : codec_g723_1b.o $(LIBG723B)
codec_gsm.so: codec_gsm.o $(LIBGSM)
$(CC) -shared -Xlinker -x -o $@ $< $(LIBGSM)
codec_lpc10.so: codec_lpc10.o $(LIBLPC10)
$(CC) -shared -Xlinker -x -o $@ $< $(LIBLPC10) -lm
codec_mp3_d.so: codec_mp3_d.o $(LIBMP3)
$(CC) -shared -Xlinker -x -o $@ $< $(LIBMP3)

2
codecs/codec_g723_1.c Executable file → Normal file
View File

@@ -200,7 +200,7 @@ static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f
#ifdef ANNEX_B
Decod(&tmp->dec, tmpdata, f->data, 0);
for (x=0;x<Frame;x++)
(tmp->buf + tmp->tail)[x] = tmpdata[x];
(tmp->buf + tmp->tail)[x] = (short)tmpdata[x];
#else
Decod(&tmp->dec, tmp->buf + tmp->tail, f->data, 0);
#endif

0
codecs/codec_gsm.c Executable file → Normal file
View File

348
codecs/codec_lpc10.c Normal file
View File

@@ -0,0 +1,348 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Translate between signed linear and LPC10 (Linear Predictor Code)
*
* The lpc10 code is from a library used by nautilus, modified to be a bit
* nicer to the compiler.
*
* See http://www.arl.wustl.edu/~jaf/
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/translate.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include <pthread.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include "lpc10/lpc10.h"
/* Sample frame data */
#include "slin_lpc10_ex.h"
#include "lpc10_slin_ex.h"
/* We use a very strange format here... I have no idea why... The frames are 180
samples long, which isn't even an even number of milliseconds... Not only that
but we hvae to waste two bits of each frame to keep them ending on a byte boundary
because the frames are 54 bits long */
#define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
static int localusecnt=0;
static char *tdesc = "LPC10 2.4kbps (signed linear) Voice Coder";
struct ast_translator_pvt {
union {
struct lpc10_encoder_state *enc;
struct lpc10_decoder_state *dec;
} lpc10;
struct ast_frame f;
/* Space to build offset */
char offset[AST_FRIENDLY_OFFSET];
/* Buffer for our outgoing frame */
short outbuf[LPC10_SAMPLES_PER_FRAME];
/* Enough to store a full second */
short buf[8000];
int tail;
int longer;
};
#define lpc10_coder_pvt ast_translator_pvt
static struct ast_translator_pvt *lpc10_enc_new()
{
struct lpc10_coder_pvt *tmp;
tmp = malloc(sizeof(struct lpc10_coder_pvt));
if (tmp) {
if (!(tmp->lpc10.enc = create_lpc10_encoder_state())) {
free(tmp);
tmp = NULL;
}
tmp->tail = 0;
tmp->longer = 0;
localusecnt++;
}
return tmp;
}
static struct ast_translator_pvt *lpc10_dec_new()
{
struct lpc10_coder_pvt *tmp;
tmp = malloc(sizeof(struct lpc10_coder_pvt));
if (tmp) {
if (!(tmp->lpc10.dec = create_lpc10_decoder_state())) {
free(tmp);
tmp = NULL;
}
tmp->tail = 0;
tmp->longer = 0;
localusecnt++;
}
return tmp;
}
static struct ast_frame *lintolpc10_sample()
{
static struct ast_frame f;
static int longer = 0;
f.frametype = AST_FRAME_VOICE;
f.subclass = AST_FORMAT_SLINEAR;
f.datalen = sizeof(slin_lpc10_ex);
/* Assume 8000 Hz */
f.timelen = LPC10_SAMPLES_PER_FRAME/8;
f.timelen += longer;
longer = 1- longer;
f.mallocd = 0;
f.offset = 0;
f.src = __PRETTY_FUNCTION__;
f.data = slin_lpc10_ex;
return &f;
}
static struct ast_frame *lpc10tolin_sample()
{
static struct ast_frame f;
f.frametype = AST_FRAME_VOICE;
f.subclass = AST_FORMAT_LPC10;
f.datalen = sizeof(lpc10_slin_ex);
/* All frames are 22 ms long (maybe a little more -- why did he choose
LPC10_SAMPLES_PER_FRAME sample frames anyway?? */
f.timelen = LPC10_SAMPLES_PER_FRAME/8;
f.mallocd = 0;
f.offset = 0;
f.src = __PRETTY_FUNCTION__;
f.data = lpc10_slin_ex;
return &f;
}
static struct ast_frame *lpc10tolin_frameout(struct ast_translator_pvt *tmp)
{
if (!tmp->tail)
return NULL;
/* Signed linear is no particular frame size, so just send whatever
we have in the buffer in one lump sum */
tmp->f.frametype = AST_FRAME_VOICE;
tmp->f.subclass = AST_FORMAT_SLINEAR;
tmp->f.datalen = tmp->tail * 2;
/* Assume 8000 Hz */
tmp->f.timelen = tmp->tail / 8;
tmp->f.mallocd = 0;
tmp->f.offset = AST_FRIENDLY_OFFSET;
tmp->f.src = __PRETTY_FUNCTION__;
tmp->f.data = tmp->buf;
/* Reset tail pointer */
tmp->tail = 0;
#if 0
/* Save a sample frame */
{ static int samplefr = 0;
if (samplefr == 80) {
int fd;
fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
write(fd, tmp->f.data, tmp->f.datalen);
close(fd);
}
samplefr++;
}
#endif
return &tmp->f;
}
static void extract_bits(INT32 *bits, unsigned char *c)
{
int x;
for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
if (*c & (0x80 >> (x & 7)))
bits[x] = 1;
else
bits[x] = 0;
if ((x & 7) == 7)
c++;
}
}
static void build_bits(unsigned char *c, INT32 *bits)
{
unsigned char mask=0x80;
int x;
*c = 0;
for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
if (bits[x])
*c |= mask;
mask = mask >> 1;
if ((x % 8)==7) {
c++;
*c = 0;
mask = 0x80;
}
}
}
static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
{
/* Assuming there's space left, decode into the current buffer at
the tail location */
int x;
float tmpbuf[LPC10_SAMPLES_PER_FRAME];
short *sd;
INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) {
sd = tmp->buf + tmp->tail;
extract_bits(bits, f->data);
if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
ast_log(LOG_WARNING, "Invalid lpc10 data\n");
return -1;
}
for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
/* Convert to a real between -1.0 and 1.0 */
sd[x] = 32768.0 * tmpbuf[x];
}
tmp->tail+=LPC10_SAMPLES_PER_FRAME;
} else {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
return 0;
}
static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
{
/* Just add the frames to our stream */
/* XXX We should look at how old the rest of our stream is, and if it
is too old, then we should overwrite it entirely, otherwise we can
get artifacts of earlier talk that do not belong */
if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
tmp->tail += f->datalen/2;
} else {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
return 0;
}
static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp)
{
int x;
float tmpbuf[LPC10_SAMPLES_PER_FRAME];
INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
/* We can't work on anything less than a frame in size */
if (tmp->tail < LPC10_SAMPLES_PER_FRAME)
return NULL;
/* Encode a frame of data */
for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
tmpbuf[x] = (float)tmp->buf[x] / 32768.0;
}
lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
build_bits((unsigned char *)tmp->outbuf, bits);
tmp->f.frametype = AST_FRAME_VOICE;
tmp->f.subclass = AST_FORMAT_LPC10;
tmp->f.datalen = LPC10_BYTES_IN_COMPRESSED_FRAME;
tmp->f.timelen = 22;
/* We alternate between 22 and 23 ms to simulate 22.5 ms */
tmp->f.timelen += tmp->longer;
/* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
important for IAX use */
tmp->longer = 1 - tmp->longer;
tmp->f.mallocd = 0;
tmp->f.offset = AST_FRIENDLY_OFFSET;
tmp->f.src = __PRETTY_FUNCTION__;
tmp->f.data = tmp->outbuf;
((char *)(tmp->f.data))[LPC10_BYTES_IN_COMPRESSED_FRAME - 1] |= tmp->longer;
tmp->tail -= LPC10_SAMPLES_PER_FRAME;
/* Move the data at the end of the buffer to the front */
if (tmp->tail)
memmove(tmp->buf, tmp->buf + LPC10_SAMPLES_PER_FRAME, tmp->tail * 2);
#if 0
/* Save a sample frame */
{ static int samplefr = 0;
if (samplefr == 0) {
int fd;
fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
write(fd, tmp->f.data, tmp->f.datalen);
close(fd);
}
samplefr++;
}
#endif
return &tmp->f;
}
static void lpc10_destroy(struct ast_translator_pvt *pvt)
{
/* Enc and DEC are both just allocated, so they can be freed */
free(pvt->lpc10.enc);
free(pvt);
localusecnt--;
}
static struct ast_translator lpc10tolin =
{ "lpc10tolin",
AST_FORMAT_LPC10, AST_FORMAT_SLINEAR,
lpc10_dec_new,
lpc10tolin_framein,
lpc10tolin_frameout,
lpc10_destroy,
lpc10tolin_sample
};
static struct ast_translator lintolpc10 =
{ "lintolpc10",
AST_FORMAT_SLINEAR, AST_FORMAT_LPC10,
lpc10_enc_new,
lintolpc10_framein,
lintolpc10_frameout,
lpc10_destroy,
lintolpc10_sample
};
int unload_module(void)
{
int res;
pthread_mutex_lock(&localuser_lock);
res = ast_unregister_translator(&lintolpc10);
if (!res)
res = ast_unregister_translator(&lpc10tolin);
if (localusecnt)
res = -1;
pthread_mutex_unlock(&localuser_lock);
return res;
}
int load_module(void)
{
int res;
res=ast_register_translator(&lpc10tolin);
if (!res)
res=ast_register_translator(&lintolpc10);
else
ast_unregister_translator(&lpc10tolin);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}

0
codecs/codec_mp3_d.c Executable file → Normal file
View File

0
codecs/g723_slin_ex.h Executable file → Normal file
View File

0
codecs/gsm/COPYRIGHT Executable file → Normal file
View File

0
codecs/gsm/Makefile Executable file → Normal file
View File

0
codecs/gsm/README Executable file → Normal file
View File

0
codecs/gsm/inc/config.h Executable file → Normal file
View File

0
codecs/gsm/inc/gsm.h Executable file → Normal file
View File

0
codecs/gsm/inc/private.h Executable file → Normal file
View File

0
codecs/gsm/inc/proto.h Executable file → Normal file
View File

0
codecs/gsm/inc/unproto.h Executable file → Normal file
View File

0
codecs/gsm/src/add.c Executable file → Normal file
View File

0
codecs/gsm/src/code.c Executable file → Normal file
View File

0
codecs/gsm/src/debug.c Executable file → Normal file
View File

0
codecs/gsm/src/decode.c Executable file → Normal file
View File

0
codecs/gsm/src/gsm_create.c Executable file → Normal file
View File

0
codecs/gsm/src/gsm_decode.c Executable file → Normal file
View File

0
codecs/gsm/src/gsm_destroy.c Executable file → Normal file
View File

0
codecs/gsm/src/gsm_encode.c Executable file → Normal file
View File

0
codecs/gsm/src/gsm_explode.c Executable file → Normal file
View File

0
codecs/gsm/src/gsm_implode.c Executable file → Normal file
View File

0
codecs/gsm/src/gsm_option.c Executable file → Normal file
View File

0
codecs/gsm/src/gsm_print.c Executable file → Normal file
View File

0
codecs/gsm/src/long_term.c Executable file → Normal file
View File

0
codecs/gsm/src/lpc.c Executable file → Normal file
View File

0
codecs/gsm/src/preprocess.c Executable file → Normal file
View File

0
codecs/gsm/src/rpe.c Executable file → Normal file
View File

0
codecs/gsm/src/short_term.c Executable file → Normal file
View File

0
codecs/gsm/src/table.c Executable file → Normal file
View File

0
codecs/gsm_slin_ex.h Executable file → Normal file
View File

70
codecs/lpc10/Makefile Normal file
View File

@@ -0,0 +1,70 @@
#
# Makefile for LPC-10 speech coder library (unix)
#
# default C compiler
CC= gcc
#
# These definitions for CFLAGS and LIB_TARGET_DIR are used when one
# runs make in the lpc10 directory, without environment variables that
# override them. When make is run in this directory from a makefile
# for an application that uses the LPC10 coder, there are environment
# variables set for CFLAGS and LIB_TARGET_DIR that override these
# definitions.
#
LIB_TARGET_DIR = .
#
# -I$(LIB_TARGET_DIR) option needed so that #include "machine.h"
# directives can find the machine.h file.
#
WARNINGS = -Wall -Wno-comment -Wno-error
CFLAGS = -O3 -I$(LIB_TARGET_DIR) $(WARNINGS)
LIB = $(LIB_TARGET_DIR)/liblpc10.a
.PHONY: all clean
all: $(LIB)
ranlib $(LIB)
$(LIB): $(LIB)(f2clib.o) \
$(LIB)(analys.o) \
$(LIB)(bsynz.o) \
$(LIB)(chanwr.o) \
$(LIB)(dcbias.o) \
$(LIB)(decode.o) \
$(LIB)(deemp.o) \
$(LIB)(difmag.o) \
$(LIB)(dyptrk.o) \
$(LIB)(encode.o) \
$(LIB)(energy.o) \
$(LIB)(ham84.o) \
$(LIB)(hp100.o) \
$(LIB)(invert.o) \
$(LIB)(irc2pc.o) \
$(LIB)(ivfilt.o) \
$(LIB)(lpcdec.o) \
$(LIB)(lpcenc.o) \
$(LIB)(lpcini.o) \
$(LIB)(lpfilt.o) \
$(LIB)(median.o) \
$(LIB)(mload.o) \
$(LIB)(onset.o) \
$(LIB)(pitsyn.o) \
$(LIB)(placea.o) \
$(LIB)(placev.o) \
$(LIB)(preemp.o) \
$(LIB)(prepro.o) \
$(LIB)(random.o) \
$(LIB)(rcchk.o) \
$(LIB)(synths.o) \
$(LIB)(tbdm.o) \
$(LIB)(voicin.o) \
$(LIB)(vparms.o)
clean:
-rm -f *.o $(LIB)

89
codecs/lpc10/README Normal file
View File

@@ -0,0 +1,89 @@
Tue Aug 20 16:19:51 CDT 1996
Andy Fingerhut (jaf@arl.wustl.edu)
In release 1.4, there are quite a few hand modifications to the C code
that was automatically created from the Fortran code with f2c. They
are all summarized in change log comments at the beginning of the
changed files. All of the original files from f2c were checked in to
RCS before modification, so it is possible to see exactly what changes
were made, for the extremely curious. That precaution was also for my
benefit, in case I ever recompile the Fortran sources, and want to
make similar changes to that new C source code.
Below is the README file for this directory included with the 1.3
release of the LPC-10 package. A few parts of it are a little out of
date, but it is correct for the most part.
Sun Jul 7 15:30:31 CDT 1996
Andy Fingerhut (jaf@arl.wustl.edu)
To create the LPC-10 library, copy the appropriate makefile to the
proper name for easy use, e.g., for Unix, copy makefile.unx to the
file "Makefile". The file makefile.dos has been used with some
version of the 'nmake' utility that comes with the Microsoft C
compiler (the same one used for Nautilus v1.5a, which I believe
specifies Microsoft C version 7.0 or later).
Then edit the file lpc10.h in the directory above. It should already
be set up to work properly on any Unix compiler for which "int" is 32
bits and "short" is 16 bits, and under the Microsoft C compiler
configured so that "long" is 32 bits and "int" is 16 bits. There must
be a typedef for the two types INT32 and INT16 in that file. You
should choose types that compile to those sizes using your compiler,
because there are places in the LPC-10 code that expect INT16's to
have exactly 16 bits (at least, I *think* they must be no larger), and
INT32's to have exactly 32 bits.
A few notes on how these files were created
-------------------------------------------
(This section is mostly for my benefit, so I can remember what I did.
You don't need to read it if you just want to use this package. It
might be useful to read it if you change the Fortran sources and want
to recreate a usable library of C sources. -- Andy)
These C sources were created automatically from the Fortran sources
using f2c, for the most part. Listed below are the extra
modifications that were made after this automatic conversion. Many of
them were made so that it was not necessary to install f2c in order to
use this LPC-10 coder.
1.
Put all of those files that were necessary for only the coder, rather
than an application that uses the coder, into this subdirectory called
lpc10.
2.
Copied f2c.h from the f2c distribution into this subdirectory. Some
modifications were made to the "typedef" statements in this file, to
explicitly indicate the sizes (in bits) that different integer types
should be. The types INT32 and INT16 must be defined in a file called
lpc10.h in the directory above. Created the file f2clib.c, containing
only the functions pow_ii(), r_sign(), and i_nint() from the f2c
library.
3.
The f2c output originally had a file called contrl_com.c, that defined
a small structure containing a few variables that were used in many
different functions of the LPC10 code. Every file containing
functions that used it defined it as "extern", while contrl_com.c
actually allocated storage for the structure. Bill Dorsey, one of the
lead developers of Nautilus, said that the Microsoft C compiler had
problems either compiling this file, or linking it with all of the
other compiled files, so he just eliminated that file and removed the
"extern" keyword from the one of the files that declared it that way.
The file chosen (arbitrarily) was analys.c.
4.
Copied the makefiles for Unix and Microsoft C from the Nautilus v1.5a
distribution into the lpc10 directory. Modified them to take out
references to Nautilus. These makefiles don't create an executable,
but a library of compiled functions called liblpc10.a (Unix) or
LPC10.LIB (DOS). This library can be used when linking an executable
that calls the functions lpcini_(), lpcenc_(), and lpcdec_().

617
codecs/lpc10/analys.c Normal file
View File

@@ -0,0 +1,617 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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:16:01 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:29:08 jaf
* Initial revision
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern int analys_(real *speech, integer *voice, integer *pitch, real *rms, real *rc, struct lpc10_encoder_state *st);
/* comlen contrl_ 12 */
/*:ref: preemp_ 14 5 6 6 4 6 6 */
/*:ref: onset_ 14 7 6 4 4 4 4 4 4 */
/*:ref: placev_ 14 11 4 4 4 4 4 4 4 4 4 4 4 */
/*:ref: lpfilt_ 14 4 6 6 4 4 */
/*:ref: ivfilt_ 14 5 6 6 4 4 6 */
/*:ref: tbdm_ 14 8 6 4 4 4 6 4 4 4 */
/*:ref: voicin_ 14 12 4 6 6 4 4 6 6 4 6 4 4 4 */
/*:ref: dyptrk_ 14 6 6 4 4 4 4 4 */
/*:ref: placea_ 14 9 4 4 4 4 4 4 4 4 4 */
/*:ref: dcbias_ 14 3 4 6 6 */
/*:ref: energy_ 14 3 4 6 6 */
/*:ref: mload_ 14 6 4 4 4 6 6 6 */
/*:ref: invert_ 14 4 4 6 6 6 */
/*:ref: rcchk_ 14 3 4 6 6 */
/*:ref: initonset_ 14 0 */
/*:ref: initvoicin_ 14 0 */
/*:ref: initdyptrk_ 14 0 */
/* Rerunning f2c -P may change prototypes or declarations. */
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* Common Block Declarations */
extern struct {
integer order, lframe;
logical corrp;
} contrl_;
#define contrl_1 contrl_
/* Table of constant values */
static integer c__10 = 10;
static integer c__181 = 181;
static integer c__720 = 720;
static integer c__3 = 3;
static integer c__90 = 90;
static integer c__156 = 156;
static integer c__307 = 307;
static integer c__462 = 462;
static integer c__312 = 312;
static integer c__60 = 60;
static integer c__1 = 1;
/* ****************************************************************** */
/* ANALYS Version 55 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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:16:01 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:29:08 jaf
* Initial revision
* */
/* Revision 1.9 1996/05/23 19:41:07 jaf */
/* Commented out some unnecessary lines that were reading uninitialized */
/* values. */
/* Revision 1.8 1996/03/27 23:57:55 jaf */
/* Added some comments about which indices of the local buffers INBUF, */
/* LPBUF, etc., get read or modified by some of the subroutine calls. I */
/* just did this while trying to figure out the discrepancy between the */
/* embedded code compiled with all local variables implicitly saved, and */
/* without. */
/* I added some debugging write statements in hopes of finding a problem. */
/* None of them ever printed anything while running with the long input */
/* speech file dam9.spd provided in the distribution. */
/* Revision 1.7 1996/03/27 18:06:20 jaf */
/* Commented out access to MAXOSP, which is just a debugging variable */
/* that was defined in the COMMON block CONTRL in contrl.fh. */
/* Revision 1.6 1996/03/26 19:31:33 jaf */
/* Commented out trace statements. */
/* Revision 1.5 1996/03/21 15:19:35 jaf */
/* Added comments for ENTRY PITDEC. */
/* Revision 1.4 1996/03/19 20:54:27 jaf */
/* Added a line to INITANALYS. See comments there. */
/* Revision 1.3 1996/03/19 20:52:49 jaf */
/* Rearranged the order of the local variables quite a bit, to separate */
/* them into groups of "constants", "locals that don't need to be saved */
/* from one call to the next", and "local that do need to be saved from */
/* one call to the next". */
/* Several locals in the last set should have been given initial values, */
/* but weren't. I gave them all initial values of 0. */
/* Added a separate ENTRY INITANALYS that initializes all local state */
/* that should be, and also calls the corresponding entries of the */
/* subroutines called by ANALYS that also have local state. */
/* There used to be DATA statements in ANALYS. I got rid of most of */
/* them, and added a local logical variable FIRST that calls the entry */
/* INITANALYS on the first call to ANALYS. This is just so that one need */
/* not remember to call INITANALYS first in order for the state to be */
/* initialized. */
/* Revision 1.2 1996/03/11 23:29:32 jaf */
/* Added several comments with my own personal questions about the */
/* Fortran 77 meaning of the parameters passed to the subroutine PREEMP. */
/* Revision 1.1 1996/02/07 14:42:29 jaf */
/* Initial revision */
/* ****************************************************************** */
/* SUBROUTINE ANALYS */
/* Input: */
/* SPEECH */
/* Indices 1 through LFRAME read. */
/* Output: */
/* VOICE */
/* Indices 1 through 2 written. */
/* PITCH */
/* Written in subroutine DYPTRK, and then perhaps read and written */
/* some more. */
/* RMS */
/* Written. */
/* RC */
/* Indices 1 through ORDER written (ORDER defined in contrl.fh). */
/* 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 */
/* INITANALYS. */
/* ENTRY PITDEC */
/* Input: */
/* PITCH - Encoded pitch index */
/* Output: */
/* PTAU - Decoded pitch period */
/* This entry has no local state. It accesses a "constant" array */
/* declared in ANALYS. */
/* Subroutine */ int analys_(real *speech, integer *voice, integer
*pitch, real *rms, real *rc, struct lpc10_encoder_state *st)
{
/* Initialized data */
static integer tau[60] = { 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
35,36,37,38,39,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,
74,76,78,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,
140,144,148,152,156 };
static integer buflim[4] = { 181,720,25,720 };
static real precoef = .9375f;
/* System generated locals */
integer i__1;
/* Local variables */
real amdf[60];
integer half;
real abuf[156];
real *bias;
extern /* Subroutine */ int tbdm_(real *, integer *, integer *, integer *,
real *, integer *, integer *, integer *);
integer *awin;
integer midx, ewin[6] /* was [2][3] */;
real ivrc[2], temp;
real *zpre;
integer *vwin;
integer i__, j, lanal;
extern /* Subroutine */ int rcchk_(integer *, real *, real *), mload_(
integer *, integer *, integer *, real *, real *, real *);
real *inbuf, *pebuf;
real *lpbuf, *ivbuf;
real *rcbuf;
integer *osbuf;
extern /* Subroutine */ int onset_(real *, integer *, integer *, integer *
, integer *, integer *, integer *, struct lpc10_encoder_state *);
integer *osptr;
extern /* Subroutine */ placea_(integer *, integer *
, integer *, integer *, integer *, integer *, integer *, integer *
, integer *), dcbias_(integer *, real *, real *), placev_(integer
*, integer *, integer *, integer *, integer *, integer *, integer
*, integer *, integer *, integer *, integer *);
integer ipitch;
integer *obound;
extern /* Subroutine */ int preemp_(real *, real *, integer *, real *,
real *), voicin_(integer *, real *, real *, integer *, integer *,
real *, real *, integer *, real *, integer *, integer *, integer *,
struct lpc10_encoder_state *);
integer *voibuf;
integer mintau;
real *rmsbuf;
extern /* Subroutine */ int lpfilt_(real *, real *, integer *, integer *),
ivfilt_(real *, real *, integer *, integer *, real *), energy_(
integer *, real *, real *), invert_(integer *, real *, real *,
real *);
integer minptr, maxptr;
extern /* Subroutine */ int dyptrk_(real *, integer *, integer *, integer
*, integer *, integer *, struct lpc10_encoder_state *);
real phi[100] /* was [10][10] */, psi[10];
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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:16:01 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:29:08 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 to ANALYS */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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:16:01 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:29:08 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 */
/* Arguments to entry PITDEC (below) */
/* Parameters/constants */
/* Constants */
/* NF = Number of frames */
/* AF = Frame in which analysis is done */
/* OSLEN = Length of the onset buffer */
/* LTAU = Number of pitch lags */
/* SBUFL, SBUFH = Start and end index of speech buffers */
/* LBUFL, LBUFH = Start and end index of LPF speech buffer */
/* MINWIN, MAXWIN = Min and Max length of voicing (and analysis) windows
*/
/* PWLEN, PWINH, PWINL = Length, upper and lower limits of pitch window
*/
/* DVWINL, DVWINH = Default lower and upper limits of voicing window */
/* The tables TAU and BUFLIM, and the variable PRECOEF, are not */
/* Fortran PARAMETER's, but they are initialized with DATA */
/* statements, and never modified. Thus, they need not have SAVE */
/* statements for them to keep their values from one invocation to
*/
/* the next. */
/* Local variables that need not be saved */
/* Local state */
/* Data Buffers */
/* INBUF Raw speech (with DC bias removed each frame) */
/* PEBUF Preemphasized speech */
/* LPBUF Low pass speech buffer */
/* IVBUF Inverse filtered speech */
/* OSBUF Indexes of onsets in speech buffers */
/* VWIN Voicing window indices */
/* AWIN Analysis window indices */
/* EWIN Energy window indices */
/* VOIBUF Voicing decisions on windows in VWIN */
/* RMSBUF RMS energy */
/* RCBUF Reflection Coefficients */
/* Pitch is handled separately from the above parameters. */
/* The following variables deal with pitch: */
/* MIDX Encoded initial pitch estimate for analysis frame */
/* IPITCH Initial pitch computed for frame AF (decoded from MIDX) */
/* PITCH The encoded pitch value (index into TAU) for the present */
/* frame (delayed and smoothed by Dyptrack) */
/* Parameter adjustments */
if (speech) {
--speech;
}
if (voice) {
--voice;
}
if (rc) {
--rc;
}
/* Function Body */
/* Calculations are done on future frame due to requirements */
/* of the pitch tracker. Delay RMS and RC's 2 frames to give */
/* current frame parameters on return. */
/* Update all buffers */
inbuf = &(st->inbuf[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_ */

423
codecs/lpc10/bsynz.c Normal file
View File

@@ -0,0 +1,423 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* Common Block Declarations */
extern struct {
integer order, lframe;
logical corrp;
} contrl_;
#define contrl_1 contrl_
/* ***************************************************************** */
/* BSYNZ Version 54 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

225
codecs/lpc10/chanwr.c Normal file
View File

@@ -0,0 +1,225 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
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);
#endif
/* -- 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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);
}

95
codecs/lpc10/dcbias.c Normal file
View File

@@ -0,0 +1,95 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern int dcbias_(integer *len, real *speech, real *sigout);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ********************************************************************* */
/* DCBIAS Version 50 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

589
codecs/lpc10/decode.c Normal file
View File

@@ -0,0 +1,589 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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,' <<ERRCOR IN>>',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,'<<ERRCOR OUT>>',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,'<<DECODE OUT>>',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_ */

142
codecs/lpc10/deemp.c Normal file
View File

@@ -0,0 +1,142 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern int deemp_(real *x, integer *n, struct lpc10_decoder_state *st);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ***************************************************************** */
/* DEEMP Version 48 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

121
codecs/lpc10/difmag.c Normal file
View File

@@ -0,0 +1,121 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ********************************************************************** */
/* DIFMAG Version 49 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

387
codecs/lpc10/dyptrk.c Normal file
View File

@@ -0,0 +1,387 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* Common Block Declarations */
extern struct {
integer order, lframe;
logical corrp;
} contrl_;
#define contrl_1 contrl_
/* ********************************************************************* */
/* DYPTRK Version 52 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

349
codecs/lpc10/encode.c Normal file
View File

@@ -0,0 +1,349 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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,/,' <<ENCODE IN>>',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,'<<ENCODE OUT>>',T32,2I3,I6,I5,T50,10I8) */
return 0;
} /* encode_ */

91
codecs/lpc10/energy.c Normal file
View File

@@ -0,0 +1,91 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern int energy_(integer *len, real *speech, real *rms);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ********************************************************************* */
/* ENERGY Version 50 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

252
codecs/lpc10/f2c.h Normal file
View File

@@ -0,0 +1,252 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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)();
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)();
#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
#endif

82
codecs/lpc10/f2clib.c Normal file
View File

@@ -0,0 +1,82 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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) );
}

114
codecs/lpc10/ham84.c Normal file
View File

@@ -0,0 +1,114 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern int ham84_(integer *input, integer *output, integer *errcnt);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ***************************************************************** */
/* HAM84 Version 45G */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

157
codecs/lpc10/hp100.c Normal file
View File

@@ -0,0 +1,157 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ********************************************************************* */
/* HP100 Version 55 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

175
codecs/lpc10/invert.c Normal file
View File

@@ -0,0 +1,175 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern int invert_(integer *order, real *phi, real *psi, real *rc);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* **************************************************************** */
/* INVERT Version 45G */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

133
codecs/lpc10/irc2pc.c Normal file
View File

@@ -0,0 +1,133 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ***************************************************************** */
/* IRC2PC Version 48 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

118
codecs/lpc10/ivfilt.c Normal file
View File

@@ -0,0 +1,118 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ********************************************************************* */
/* IVFILT Version 48 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

229
codecs/lpc10/lpc10.h Normal file
View File

@@ -0,0 +1,229 @@
/*
$Log$
Revision 1.2 2000/01/05 00:20:06 markster
Version 0.1.3 from FTP
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)
typedef short INT16;
typedef int INT32;
#endif
#if defined(__MSDOS__) || defined(MSDOS)
typedef int INT16;
typedef long 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 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 init_lpc10_decoder_state (struct lpc10_decoder_state *st);
int lpc10_decode (INT32 *bits, real *speech, struct lpc10_decoder_state *st);
#endif /* __LPC10_H__ */

273
codecs/lpc10/lpcdec.c Normal file
View File

@@ -0,0 +1,273 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

163
codecs/lpc10/lpcenc.c Normal file
View File

@@ -0,0 +1,163 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* Table of constant values */
static integer c__180 = 180;
static integer c__10 = 10;
/* ***************************************************************** */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

399
codecs/lpc10/lpcini.c Normal file
View File

@@ -0,0 +1,399 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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 "f2c.h"
#include <malloc.h>
/* Common Block Declarations */
struct {
integer order, lframe;
logical corrp;
} contrl_;
#define contrl_1 contrl_
/* ***************************************************************** */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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;
}

113
codecs/lpc10/lpfilt.c Normal file
View File

@@ -0,0 +1,113 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern int lpfilt_(real *inbuf, real *lpbuf, integer *len, integer *nsamp);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* *********************************************************************** */
/* LPFILT Version 55 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

77
codecs/lpc10/median.c Normal file
View File

@@ -0,0 +1,77 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern integer median_(integer *d1, integer *d2, integer *d3);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ********************************************************************* */
/* MEDIAN Version 45G */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

151
codecs/lpc10/mload.c Normal file
View File

@@ -0,0 +1,151 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ***************************************************************** */
/* MLOAD Version 48 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

306
codecs/lpc10/onset.c Normal file
View File

@@ -0,0 +1,306 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* Table of constant values */
static real c_b2 = 1.f;
/* ****************************************************************** */
/* ONSET Version 49 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

556
codecs/lpc10/pitsyn.c Normal file
View File

@@ -0,0 +1,556 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ***************************************************************** */
/* PITSYN Version 53 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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, 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

218
codecs/lpc10/placea.c Normal file
View File

@@ -0,0 +1,218 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* *********************************************************************** */
/* PLACEA Version 48 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

257
codecs/lpc10/placev.c Normal file
View File

@@ -0,0 +1,257 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ****************************************************************** */
/* PLACEV Version 48 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

132
codecs/lpc10/preemp.c Normal file
View File

@@ -0,0 +1,132 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ******************************************************************* */
/* PREEMP Version 55 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

105
codecs/lpc10/prepro.c Normal file
View File

@@ -0,0 +1,105 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* Table of constant values */
static integer c__1 = 1;
/* ********************************************************************* */
/* PREPRO Version 48 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

113
codecs/lpc10/random.c Normal file
View File

@@ -0,0 +1,113 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern integer random_(struct lpc10_decoder_state *st);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ********************************************************************** */
/* RANDOM Version 49 */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

107
codecs/lpc10/rcchk.c Normal file
View File

@@ -0,0 +1,107 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#ifdef P_R_O_T_O_T_Y_P_E_S
extern int rcchk_(integer *order, real *rc1f, real *rc2f);
#endif
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* ********************************************************************* */
/* RCCHK Version 45G */
/* $Log$
* Revision 1.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

392
codecs/lpc10/synths.c Normal file
View File

@@ -0,0 +1,392 @@
/*
$Log$
Revision 1.2 2000/01/05 08:20:39 markster
Version 0.1.3 from FTP
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
*
*/
#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
/* -- translated by f2c (version 19951025).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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];
extern /* Subroutine */ bsynz_(real *, integer *,
integer *, real *, real *, real *, real *, struct lpc10_decoder_state *), irc2pc_(real *, real *
, integer *, real *, real *);
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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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.2 2000/01/05 08:20:39 markster
* Version 0.1.3 from FTP
*
/* 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_ */

Some files were not shown because too many files have changed in this diff Show More