first commit
This commit is contained in:
+171
@@ -0,0 +1,171 @@
|
||||
|
||||
set(IAXCLIENT_BASE_SOURCES
|
||||
audio_encode.c
|
||||
audio_file.c
|
||||
audio_openal.c
|
||||
codec_alaw.c
|
||||
codec_gsm.c
|
||||
codec_ulaw.c
|
||||
codec_speex.c
|
||||
iaxclient_lib.c
|
||||
spandsp/plc.c
|
||||
)
|
||||
|
||||
set(LIBIAX2_SOURCES
|
||||
libiax2/src/iax.c
|
||||
libiax2/src/iax2-parser.c
|
||||
libiax2/src/jitterbuf.c
|
||||
libiax2/src/md5.c
|
||||
)
|
||||
|
||||
if (SG_SOUND_USES_OPENALSOFT)
|
||||
message(STATUS "Using OpenAL-soft for IAX OpenAL backend")
|
||||
find_package(OpenAL CONFIG REQUIRED)
|
||||
else()
|
||||
find_package(OpenAL REQUIRED)
|
||||
endif()
|
||||
|
||||
|
||||
add_library(iaxclient_lib STATIC
|
||||
${IAXCLIENT_BASE_SOURCES} ${LIBIAX2_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(iaxclient_lib PRIVATE Threads::Threads ${OPENAL_LIBRARY})
|
||||
target_include_directories(iaxclient_lib PUBLIC ${PROJECT_SOURCE_DIR}/3rdparty/iaxclient/lib)
|
||||
target_include_directories(iaxclient_lib PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/iaxclient/lib/libiax2/src ${OPENAL_INCLUDE_DIR})
|
||||
|
||||
target_compile_definitions(iaxclient_lib PRIVATE AUDIO_OPENAL=1 LIBIAX LIBVER="SVN 261")
|
||||
|
||||
# pass this through since it affects how we include al.h
|
||||
if (SG_SOUND_USES_OPENALSOFT)
|
||||
target_compile_definitions(iaxclient_lib PRIVATE SG_SOUND_USES_OPENALSOFT)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
target_compile_definitions(iaxclient_lib PRIVATE MACOSX)
|
||||
endif(APPLE)
|
||||
|
||||
if (WIN32)
|
||||
target_sources(iaxclient_lib PRIVATE winfuncs.c)
|
||||
else()
|
||||
target_sources(iaxclient_lib PRIVATE unixfuncs.c)
|
||||
endif(WIN32)
|
||||
|
||||
|
||||
if (MSVC)
|
||||
# turn off various warnings
|
||||
set(WFLAGS)
|
||||
foreach(warning 4244 4305 4996)
|
||||
list(APPEND WFLAGS "/wd${warning}")
|
||||
endforeach()
|
||||
target_compile_definitions(iaxclient_lib PRIVATE ${WFLAGS})
|
||||
endif ()
|
||||
|
||||
if (SYSTEM_GSM)
|
||||
set(Gsm_FIND_REQUIRED TRUE)
|
||||
find_package(Gsm)
|
||||
endif(SYSTEM_GSM)
|
||||
|
||||
if (SYSTEM_GSM AND GSM_FOUND)
|
||||
message(STATUS "Using GSM includes at: ${GSM_INCLUDE_DIR}")
|
||||
message(STATUS "Using GSM libraries: ${GSM_LIBRARIES}")
|
||||
target_include_directories(iaxclient_lib PRIVATE ${GSM_INCLUDE_DIR})
|
||||
target_link_libraries(iaxclient_lib PRIVATE ${GSM_LIBRARIES})
|
||||
else()
|
||||
# add local GSM files
|
||||
target_sources(iaxclient_lib PRIVATE
|
||||
gsm/src/add.c
|
||||
gsm/src/code.c
|
||||
gsm/src/debug.c
|
||||
gsm/src/decode.c
|
||||
gsm/src/gsm_create.c
|
||||
gsm/src/gsm_decode.c
|
||||
gsm/src/gsm_destroy.c
|
||||
gsm/src/gsm_encode.c
|
||||
gsm/src/gsm_explode.c
|
||||
gsm/src/gsm_implode.c
|
||||
gsm/src/gsm_option.c
|
||||
gsm/src/gsm_print.c
|
||||
gsm/src/long_term.c
|
||||
gsm/src/lpc.c
|
||||
gsm/src/preprocess.c
|
||||
gsm/src/rpe.c
|
||||
gsm/src/short_term.c
|
||||
gsm/src/table.c
|
||||
)
|
||||
|
||||
target_include_directories(iaxclient_lib PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/iaxclient/lib/gsm/inc)
|
||||
target_compile_definitions(iaxclient_lib PRIVATE HAS_STRING_H HAS_STDLIB_H)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(iaxclient_lib PRIVATE CODEC_GSM)
|
||||
|
||||
if (SYSTEM_SPEEX)
|
||||
set(Speex_FIND_REQUIRED TRUE)
|
||||
set(Speexdsp_FIND_REQUIRED TRUE)
|
||||
find_package(Speex)
|
||||
find_package(Speexdsp)
|
||||
endif()
|
||||
|
||||
if (SPEEX_FOUND AND SPEEXDSP_FOUND)
|
||||
|
||||
message(STATUS "Using speex includes at: ${SPEEX_INCLUDE_DIR}")
|
||||
message(STATUS "Using speex libraries: ${SPEEX_LIBRARIES}")
|
||||
message(STATUS "Using speex extended library includes at: ${SPEEXDSP_INCLUDE_DIR}")
|
||||
message(STATUS "Using speex extended library libraries: ${SPEEXDSP_LIBRARIES}")
|
||||
|
||||
target_include_directories(iaxclient_lib PRIVATE ${SPEEX_INCLUDE_DIR} ${SPEEXDSP_INCLUDE_DIR})
|
||||
target_link_libraries(iaxclient_lib PRIVATE ${SPEEX_LIBRARIES} ${SPEEXDSP_LIBRARIES})
|
||||
else()
|
||||
target_sources(iaxclient_lib PRIVATE
|
||||
libspeex/bits.c
|
||||
libspeex/cb_search.c
|
||||
libspeex/exc_10_16_table.c
|
||||
libspeex/exc_10_32_table.c
|
||||
libspeex/exc_20_32_table.c
|
||||
libspeex/exc_5_256_table.c
|
||||
libspeex/exc_5_64_table.c
|
||||
libspeex/exc_8_128_table.c
|
||||
libspeex/filters.c
|
||||
libspeex/gain_table.c
|
||||
libspeex/gain_table_lbr.c
|
||||
libspeex/hexc_10_32_table.c
|
||||
libspeex/hexc_table.c
|
||||
libspeex/high_lsp_tables.c
|
||||
libspeex/jitter.c
|
||||
libspeex/lbr_48k_tables.c
|
||||
libspeex/lpc.c
|
||||
libspeex/lsp.c
|
||||
libspeex/lsp_tables_nb.c
|
||||
libspeex/ltp.c
|
||||
libspeex/math_approx.c
|
||||
libspeex/mdf.c
|
||||
libspeex/medfilter.c
|
||||
libspeex/misc.c
|
||||
libspeex/modes.c
|
||||
libspeex/nb_celp.c
|
||||
libspeex/preprocess.c
|
||||
libspeex/quant_lsp.c
|
||||
libspeex/sb_celp.c
|
||||
libspeex/smallft.c
|
||||
libspeex/speex.c
|
||||
libspeex/speex_callbacks.c
|
||||
libspeex/speex_header.c
|
||||
libspeex/stereo.c
|
||||
libspeex/vbr.c
|
||||
libspeex/vq.c
|
||||
)
|
||||
|
||||
target_include_directories(iaxclient_lib PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/iaxclient/lib/libspeex/include)
|
||||
endif()
|
||||
|
||||
# never used for the moment
|
||||
# if (ENABLE_ALSA)
|
||||
# target_sources(iaxclient_lib PRIVATE audio_alsa.c)
|
||||
# endif(ENABLE_ALSA)
|
||||
|
||||
# if (ENABLE_PORTAUDIO)
|
||||
# target_sources(iaxclient_lib PRIVATE audio_portaudio.c)
|
||||
# endif(ENABLE_PORTAUDIO)
|
||||
|
||||
# eof
|
||||
Vendored
+101
@@ -0,0 +1,101 @@
|
||||
TODO items:
|
||||
|
||||
|
||||
1) Audio driver work:
|
||||
Properly abstract audio drivers (currently, we use only
|
||||
portaudio, but we may also want to support others.
|
||||
The most likely candidate here would be zaptel devices.
|
||||
|
||||
Instead of the "switch" statements in the code, define an audio
|
||||
driver structure, with
|
||||
|
||||
- function pointers for actual driver entry points.
|
||||
initialization: (scans available devices, sets up data
|
||||
structures)
|
||||
destruction: (stops everything, cleans up)
|
||||
"start": starts audio for a particular call?
|
||||
"stop": stops audio for a particular call?
|
||||
"playsound": plays a particular sound: can be used for
|
||||
incoming call notification, ringback, dialtone etc?
|
||||
"select": select input and output devices to use?
|
||||
[maybe extend this for zap devices to have "ring", etc
|
||||
functions?]
|
||||
|
||||
|
||||
- Common audio driver data members:
|
||||
a) perhaps an array of devices the driver has found,
|
||||
with for each device, a device name, an
|
||||
indication of whether this device is the default
|
||||
input or output, and whether this device
|
||||
supports input, output, or both.
|
||||
|
||||
For portaudio, we probably want to switch to the "standard"
|
||||
portaudio callback interface, and away from pablio, which isn't
|
||||
really robust enough for our needs once we do this stuff.
|
||||
|
||||
|
||||
|
||||
2) Codecs: (I think that someone is working on this)
|
||||
|
||||
Currently, the library assumes that all calls will be GSM only,
|
||||
and further assumes that all frames will be 20ms. It can
|
||||
control the frame size (within reason) for frames it sends out,
|
||||
but should deal gracefully with incoming frames that aren't
|
||||
20ms.
|
||||
|
||||
Codecs should probably be implemented via a similar set of
|
||||
structure abstractions as audio drivers, above. They also need
|
||||
to handle incoming packets which may switch formats abruptly(?).
|
||||
|
||||
DONE (or, at least, mostly done):
|
||||
==============================================================
|
||||
Call handling
|
||||
currently, the library really only supports one call, and not
|
||||
very well. It should have a collection of calls (either an
|
||||
array, or a linked list), and keep track of the current state of
|
||||
each call.
|
||||
|
||||
An array might be easiest to manage, and would map well to a
|
||||
softphone client. We would then just refer to calls by their
|
||||
index, and a GUI client might present these like call
|
||||
appearances on their display.
|
||||
|
||||
Incoming calls might come in on the first free call appearance,
|
||||
and outgoing calls by default would do the same.
|
||||
|
||||
The state of each call might be similar to phonecore
|
||||
(incoming_incomplete, incoming, outgoing_incomplete, outgoing),
|
||||
but we'd also have to keep track of which call, if any, we
|
||||
currenly have "selected" -- i.e. which one we should connect to
|
||||
the audio system.
|
||||
|
||||
We'd need to send events to the client whenever a call changed
|
||||
"state" in any way.
|
||||
|
||||
We can make the number of calls in the array defined at runtime
|
||||
when the library is initialized. A very simple client like
|
||||
testcall would just ask for a single call, so it wouldn't have
|
||||
to worry about a lot of this.
|
||||
|
||||
Events:
|
||||
We might want to consolidate the (currently three) callbacks
|
||||
that the library makes to clients, into a single callback, that
|
||||
passes back a structure with event info. I was thinking of a
|
||||
structure with an event type, and then a union of different
|
||||
structures depending on the event type.
|
||||
|
||||
The only thing is that we might want to decide whether or not,
|
||||
or how clients will "register" for different event types, even
|
||||
if they're handled through the same callback mechanism.
|
||||
|
||||
Ideally, the library would handle all of the events itself, via
|
||||
some "default" handlers. (I.e. for messages, it might just print
|
||||
them to stdout or stderr. For incoming calls, it might accept
|
||||
them by default).
|
||||
|
||||
So, the choices then are whether the client should register for
|
||||
individual events, or perhaps it can just decline events as they
|
||||
happen, and then the library could handle them.
|
||||
|
||||
|
||||
|
||||
Vendored
+277
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2006 Panfilov Dmitry
|
||||
*
|
||||
* Contributors:
|
||||
* Panfilov Dmitry
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iaxclient_lib.h"
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
static snd_pcm_t *stream_out;
|
||||
static snd_pcm_t *stream_in;
|
||||
|
||||
#define FRAMES_PER_BUFFER 80 /* 80 frames == 10ms */
|
||||
|
||||
|
||||
static int alsa_play_sound(struct iaxc_sound *inSound, int ring) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alsa_stop_sound(int soundID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int alsa_start (struct iaxc_audio_driver *d ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alsa_stop (struct iaxc_audio_driver *d ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void alsa_shutdown_audio()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int alsa_input(struct iaxc_audio_driver *d, void *samples, int *nSamples) {
|
||||
|
||||
/* we don't return partial buffers */
|
||||
long r;
|
||||
long byteread=*nSamples;
|
||||
static int h;
|
||||
*nSamples=0;
|
||||
snd_pcm_start(stream_in);
|
||||
if(h==1) { h=0; return 0;}
|
||||
do{
|
||||
r = snd_pcm_readi(stream_in, samples, byteread);
|
||||
if (r == -EAGAIN){
|
||||
continue;
|
||||
}
|
||||
if (r == - EPIPE) {
|
||||
snd_pcm_prepare(stream_in);
|
||||
continue;
|
||||
}
|
||||
samples += (r * 2);
|
||||
byteread -= r;
|
||||
*nSamples += r;
|
||||
}while(r >=0 && byteread >0);
|
||||
h=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alsa_output(struct iaxc_audio_driver *d, void *samples, int nSamples) {
|
||||
|
||||
long r;
|
||||
snd_pcm_start(stream_out);
|
||||
while (nSamples > 0) {
|
||||
r = snd_pcm_writei(stream_out, samples, nSamples);
|
||||
if (r == -EAGAIN){
|
||||
continue;
|
||||
}
|
||||
if (r == - EPIPE) {
|
||||
snd_pcm_prepare(stream_out);
|
||||
continue;
|
||||
}
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "r=%d\n",r);
|
||||
}
|
||||
samples += r * 2;
|
||||
nSamples -= r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alsa_select_devices (struct iaxc_audio_driver *d, int input, int output, int ring) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alsa_selected_devices (struct iaxc_audio_driver *d, int *input, int *output, int *ring) {
|
||||
*input = 0;
|
||||
*output = 0;
|
||||
*ring = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alsa_destroy (struct iaxc_audio_driver *d )
|
||||
{
|
||||
/* TODO: something should happen here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
double alsa_input_level_get(struct iaxc_audio_driver *d){
|
||||
return -1;
|
||||
}
|
||||
|
||||
double alsa_output_level_get(struct iaxc_audio_driver *d){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int alsa_input_level_set(struct iaxc_audio_driver *d, double level){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int alsa_output_level_set(struct iaxc_audio_driver *d, double level){
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* initialize audio driver */
|
||||
int alsa_initialize (struct iaxc_audio_driver *d ,int sample_rate) {
|
||||
int i;
|
||||
int err;
|
||||
short buf[128];
|
||||
snd_pcm_hw_params_t *hw_params;
|
||||
snd_pcm_sw_params_t *sw_params;
|
||||
|
||||
if ((err = snd_pcm_open (&stream_out, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
||||
fprintf (stderr, "cannot open audio device default (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_any (stream_out, hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_access (stream_out, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
||||
fprintf (stderr, "cannot set access type (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_format (stream_out, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
|
||||
fprintf (stderr, "cannot set sample format (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_rate (stream_out, hw_params, sample_rate, 0)) < 0) {
|
||||
fprintf (stderr, "cannot set sample rate (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_channels (stream_out, hw_params, 1)) < 0) {
|
||||
fprintf (stderr, "cannot set channel count (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params (stream_out, hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot set parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
snd_pcm_sw_params_malloc(&sw_params);
|
||||
|
||||
err = snd_pcm_sw_params_current(stream_out, sw_params);
|
||||
if (err < 0) {
|
||||
printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
err = snd_pcm_sw_params_set_start_threshold(stream_out, sw_params, 80);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
err = snd_pcm_sw_params(stream_out, sw_params);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to set sw params for playback: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_open (&stream_in, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0) {
|
||||
fprintf (stderr, "cannot open audio device default (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_any (stream_in, hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_access (stream_in, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
||||
fprintf (stderr, "cannot set access type (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_format (stream_in, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
|
||||
fprintf (stderr, "cannot set sample format (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_rate (stream_in, hw_params, sample_rate, 0)) < 0) {
|
||||
fprintf (stderr, "cannot set sample rate (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_channels (stream_in, hw_params, 1)) < 0) {
|
||||
fprintf (stderr, "cannot set channel count (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params (stream_in, hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot set parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
err = snd_pcm_sw_params_current(stream_in, sw_params);
|
||||
if (err < 0) {
|
||||
printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
err = snd_pcm_sw_params_set_start_threshold(stream_in, sw_params, 80);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
err = snd_pcm_sw_params(stream_in, sw_params);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to set sw params for playback: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
if ((err = snd_pcm_prepare (stream_in)) < 0) {
|
||||
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_prepare (stream_out)) < 0) {
|
||||
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
||||
snd_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
d->initialize = alsa_initialize;
|
||||
d->destroy = alsa_destroy;
|
||||
d->select_devices = alsa_select_devices;
|
||||
d->selected_devices = alsa_selected_devices;
|
||||
d->start = alsa_start;
|
||||
d->stop = alsa_stop;
|
||||
d->output = alsa_output;
|
||||
d->input = alsa_input;
|
||||
d->input_level_get = alsa_input_level_get;
|
||||
d->input_level_set = alsa_input_level_set;
|
||||
d->output_level_get = alsa_output_level_get;
|
||||
d->output_level_set = alsa_output_level_set;
|
||||
d->play_sound = alsa_play_sound;
|
||||
d->stop_sound = alsa_stop_sound;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_ALSA_H
|
||||
#define _AUDIO_ALSA_H
|
||||
|
||||
int alsa_initialize();
|
||||
|
||||
#endif
|
||||
+414
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
* Michael Van Donselaar <mvand@vandonselaar.org>
|
||||
* Shawn Lawrence <shawn.lawrence@terracecomm.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#include "audio_encode.h"
|
||||
#include "iaxclient_lib.h"
|
||||
#include "iax-client.h"
|
||||
#ifdef CODEC_GSM
|
||||
#include "codec_gsm.h"
|
||||
#endif
|
||||
#include "codec_ulaw.h"
|
||||
#include "codec_alaw.h"
|
||||
|
||||
#include "codec_speex.h"
|
||||
#include <speex/speex_preprocess.h>
|
||||
|
||||
#ifdef CODEC_ILBC
|
||||
#include "codec_ilbc.h"
|
||||
#endif
|
||||
|
||||
float iaxci_silence_threshold = AUDIO_ENCODE_SILENCE_DB;
|
||||
|
||||
static float input_level = 0.0f;
|
||||
static float output_level = 0.0f;
|
||||
|
||||
static SpeexPreprocessState *st = NULL;
|
||||
static int speex_state_size = 0;
|
||||
static int speex_state_rate = 0;
|
||||
|
||||
int iaxci_filters = IAXC_FILTER_AGC|IAXC_FILTER_DENOISE|IAXC_FILTER_AAGC|IAXC_FILTER_CN;
|
||||
|
||||
/* use to measure time since last audio was processed */
|
||||
static struct timeval timeLastInput ;
|
||||
static struct timeval timeLastOutput ;
|
||||
|
||||
static struct iaxc_speex_settings speex_settings =
|
||||
{
|
||||
1, /* decode_enhance */
|
||||
-1, /* float quality */
|
||||
-1, /* bitrate */
|
||||
0, /* vbr */
|
||||
0, /* abr */
|
||||
3 /* complexity */
|
||||
};
|
||||
|
||||
|
||||
static float vol_to_db(float vol)
|
||||
{
|
||||
/* avoid calling log10() on zero which yields inf or
|
||||
* negative numbers which yield nan */
|
||||
if ( vol <= 0.0f )
|
||||
return AUDIO_ENCODE_SILENCE_DB;
|
||||
else
|
||||
return log10f(vol) * 20.0f;
|
||||
}
|
||||
|
||||
static int do_level_callback()
|
||||
{
|
||||
static struct timeval last = {0,0};
|
||||
struct timeval now;
|
||||
float input_db;
|
||||
float output_db;
|
||||
|
||||
now = iax_tvnow();
|
||||
|
||||
if ( last.tv_sec != 0 && iaxci_usecdiff(&now, &last) < 100000 )
|
||||
return 0;
|
||||
|
||||
last = now;
|
||||
|
||||
/* if input has not been processed in the last second, set to silent */
|
||||
input_db = iaxci_usecdiff(&now, &timeLastInput) < 1000000 ?
|
||||
vol_to_db(input_level) : AUDIO_ENCODE_SILENCE_DB;
|
||||
|
||||
/* if output has not been processed in the last second, set to silent */
|
||||
output_db = iaxci_usecdiff(&now, &timeLastOutput) < 1000000 ?
|
||||
vol_to_db(output_level) : AUDIO_ENCODE_SILENCE_DB;
|
||||
|
||||
iaxci_do_levels_callback(input_db, output_db);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_speex_filters()
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !st )
|
||||
return;
|
||||
|
||||
i = 1; /* always make VAD decision */
|
||||
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_VAD, &i);
|
||||
i = (iaxci_filters & IAXC_FILTER_AGC) ? 1 : 0;
|
||||
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &i);
|
||||
i = (iaxci_filters & IAXC_FILTER_DENOISE) ? 1 : 0;
|
||||
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i);
|
||||
|
||||
/*
|
||||
* We can tweak these parameters to play with VAD sensitivity.
|
||||
* For now, we use the default values since it seems they are a good starting point.
|
||||
* However, if need be, this is the code that needs to change
|
||||
*/
|
||||
i = 35;
|
||||
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_PROB_START, &i);
|
||||
i = 20;
|
||||
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &i);
|
||||
}
|
||||
|
||||
static void calculate_level(short *audio, int len, float *level)
|
||||
{
|
||||
int big_sample = 0;
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < len; i++ )
|
||||
{
|
||||
const int sample = abs(audio[i]);
|
||||
big_sample = sample > big_sample ?
|
||||
sample : big_sample;
|
||||
}
|
||||
|
||||
*level += ((float)big_sample / 32767.0f - *level) / 5.0f;
|
||||
}
|
||||
|
||||
|
||||
static int input_postprocess(void *audio, int len, int rate)
|
||||
{
|
||||
static float lowest_volume = 1.0f;
|
||||
float volume;
|
||||
int silent = 0;
|
||||
|
||||
if ( !st || speex_state_size != len || speex_state_rate != rate )
|
||||
{
|
||||
if (st)
|
||||
speex_preprocess_state_destroy(st);
|
||||
st = speex_preprocess_state_init(len,rate);
|
||||
speex_state_size = len;
|
||||
speex_state_rate = rate;
|
||||
set_speex_filters();
|
||||
}
|
||||
|
||||
calculate_level((short *)audio, len, &input_level);
|
||||
|
||||
/* only preprocess if we're interested in VAD, AGC, or DENOISE */
|
||||
if ( (iaxci_filters & (IAXC_FILTER_DENOISE | IAXC_FILTER_AGC)) ||
|
||||
iaxci_silence_threshold > 0.0f )
|
||||
silent = !speex_preprocess(st, (spx_int16_t *)audio, NULL);
|
||||
|
||||
/* Analog AGC: Bring speex AGC gain out to mixer, with lots of hysteresis */
|
||||
/* use a higher continuation threshold for AAGC than for VAD itself */
|
||||
if ( !silent &&
|
||||
iaxci_silence_threshold != 0.0f &&
|
||||
(iaxci_filters & IAXC_FILTER_AGC) &&
|
||||
(iaxci_filters & IAXC_FILTER_AAGC)
|
||||
)
|
||||
{
|
||||
static int i = 0;
|
||||
|
||||
i++;
|
||||
|
||||
if ( (i & 0x3f) == 0 )
|
||||
{
|
||||
float loudness;
|
||||
#ifdef SPEEX_PREPROCESS_GET_AGC_LOUDNESS
|
||||
speex_preprocess_ctl(st, SPEEX_PREPROCESS_GET_AGC_LOUDNESS, &loudness);
|
||||
#else
|
||||
loudness = st->loudness2;
|
||||
#endif
|
||||
if ( loudness > 8000.0f || loudness < 4000.0f )
|
||||
{
|
||||
const float level = iaxc_input_level_get();
|
||||
|
||||
if ( loudness > 16000.0f && level > 0.5f )
|
||||
{
|
||||
/* lower quickly if we're really too hot */
|
||||
iaxc_input_level_set(level - 0.2f);
|
||||
}
|
||||
else if ( loudness > 8000.0f && level >= 0.15f )
|
||||
{
|
||||
/* lower less quickly if we're a bit too hot */
|
||||
iaxc_input_level_set(level - 0.1f);
|
||||
}
|
||||
else if ( loudness < 4000.0f && level <= 0.9f )
|
||||
{
|
||||
/* raise slowly if we're cold */
|
||||
iaxc_input_level_set(level + 0.1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is ugly. Basically just don't get volume level if speex thought
|
||||
* we were silent. Just set it to 0 in that case */
|
||||
if ( iaxci_silence_threshold > 0.0f && silent )
|
||||
input_level = 0.0f;
|
||||
|
||||
do_level_callback();
|
||||
|
||||
volume = vol_to_db(input_level);
|
||||
|
||||
if ( volume < lowest_volume )
|
||||
lowest_volume = volume;
|
||||
|
||||
if ( iaxci_silence_threshold > 0.0f )
|
||||
return silent;
|
||||
else
|
||||
return volume < iaxci_silence_threshold;
|
||||
}
|
||||
|
||||
static int output_postprocess(void *audio, int len)
|
||||
{
|
||||
calculate_level((short *)audio, len, &output_level);
|
||||
|
||||
do_level_callback();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iaxc_audio_codec *create_codec(int format)
|
||||
{
|
||||
switch (format & IAXC_AUDIO_FORMAT_MASK)
|
||||
{
|
||||
#ifdef CODEC_GSM
|
||||
case IAXC_FORMAT_GSM:
|
||||
return codec_audio_gsm_new();
|
||||
#endif
|
||||
case IAXC_FORMAT_ULAW:
|
||||
return codec_audio_ulaw_new();
|
||||
case IAXC_FORMAT_ALAW:
|
||||
return codec_audio_alaw_new();
|
||||
case IAXC_FORMAT_SPEEX:
|
||||
return codec_audio_speex_new(&speex_settings);
|
||||
#ifdef CODEC_ILBC
|
||||
case IAXC_FORMAT_ILBC:
|
||||
return codec_audio_ilbc_new();
|
||||
#endif
|
||||
default:
|
||||
/* ERROR: codec not supported */
|
||||
fprintf(stderr, "ERROR: Codec not supported: %d\n", format);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT void iaxc_set_speex_settings(int decode_enhance, float quality,
|
||||
int bitrate, int vbr, int abr, int complexity)
|
||||
{
|
||||
speex_settings.decode_enhance = decode_enhance;
|
||||
speex_settings.quality = quality;
|
||||
speex_settings.bitrate = bitrate;
|
||||
speex_settings.vbr = vbr;
|
||||
speex_settings.abr = abr;
|
||||
speex_settings.complexity = complexity;
|
||||
}
|
||||
|
||||
int audio_send_encoded_audio(struct iaxc_call *call, int callNo, void *data,
|
||||
int format, int samples)
|
||||
{
|
||||
unsigned char outbuf[1024];
|
||||
int outsize = 1024;
|
||||
int silent;
|
||||
int insize = samples;
|
||||
|
||||
/* update last input timestamp */
|
||||
timeLastInput = iax_tvnow();
|
||||
|
||||
silent = input_postprocess(data, insize, 8000);
|
||||
|
||||
if(silent)
|
||||
{
|
||||
if(!call->tx_silent)
|
||||
{ /* send a Comfort Noise Frame */
|
||||
call->tx_silent = 1;
|
||||
if ( iaxci_filters & IAXC_FILTER_CN )
|
||||
iax_send_cng(call->session, 10, NULL, 0);
|
||||
}
|
||||
return 0; /* poof! no encoding! */
|
||||
}
|
||||
|
||||
/* we're going to send voice now */
|
||||
call->tx_silent = 0;
|
||||
|
||||
/* destroy encoder if it is incorrect type */
|
||||
if(call->encoder && call->encoder->format != format)
|
||||
{
|
||||
call->encoder->destroy(call->encoder);
|
||||
call->encoder = NULL;
|
||||
}
|
||||
|
||||
/* just break early if there's no format defined: this happens for the
|
||||
* first couple of frames of new calls */
|
||||
if(format == 0) return 0;
|
||||
|
||||
/* create encoder if necessary */
|
||||
if(!call->encoder)
|
||||
{
|
||||
call->encoder = create_codec(format);
|
||||
}
|
||||
|
||||
if(!call->encoder)
|
||||
{
|
||||
/* ERROR: no codec */
|
||||
fprintf(stderr, "ERROR: Codec could not be created: %d\n", format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(call->encoder->encode(call->encoder, &insize, (short *)data,
|
||||
&outsize, outbuf))
|
||||
{
|
||||
/* ERROR: codec error */
|
||||
fprintf(stderr, "ERROR: encode error: %d\n", format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(samples-insize == 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR encoding (no samples output (samples=%d)\n", samples);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Send the encoded audio data back to the app if required
|
||||
// TODO: fix the stupid way in which the encoded audio size is returned
|
||||
if ( iaxc_get_audio_prefs() & IAXC_AUDIO_PREF_RECV_LOCAL_ENCODED )
|
||||
iaxci_do_audio_callback(callNo, 0, IAXC_SOURCE_LOCAL, 1,
|
||||
call->encoder->format & IAXC_AUDIO_FORMAT_MASK,
|
||||
sizeof(outbuf) - outsize, outbuf);
|
||||
|
||||
if(iax_send_voice(call->session,format, outbuf,
|
||||
sizeof(outbuf) - outsize, samples-insize) == -1)
|
||||
{
|
||||
fprintf(stderr, "Failed to send voice! %s\n", iax_errstr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* decode encoded audio; return the number of bytes decoded
|
||||
* negative indicates error */
|
||||
int audio_decode_audio(struct iaxc_call * call, void * out, void * data, int len,
|
||||
int format, int * samples)
|
||||
{
|
||||
int insize = len;
|
||||
int outsize = *samples;
|
||||
|
||||
timeLastOutput = iax_tvnow();
|
||||
|
||||
if ( format == 0 )
|
||||
{
|
||||
fprintf(stderr, "audio_decode_audio: Format is zero (should't happen)!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* destroy decoder if it is incorrect type */
|
||||
if ( call->decoder && call->decoder->format != format )
|
||||
{
|
||||
call->decoder->destroy(call->decoder);
|
||||
call->decoder = NULL;
|
||||
}
|
||||
|
||||
/* create decoder if necessary */
|
||||
if ( !call->decoder )
|
||||
{
|
||||
call->decoder = create_codec(format);
|
||||
}
|
||||
|
||||
if ( !call->decoder )
|
||||
{
|
||||
fprintf(stderr, "ERROR: Codec could not be created: %d\n",
|
||||
format);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( call->decoder->decode(call->decoder,
|
||||
&insize, (unsigned char *)data,
|
||||
&outsize, (short *)out) )
|
||||
{
|
||||
fprintf(stderr, "ERROR: decode error: %d\n", format);
|
||||
return -1;
|
||||
}
|
||||
|
||||
output_postprocess(out, *samples - outsize);
|
||||
|
||||
*samples = outsize;
|
||||
return len - insize;
|
||||
}
|
||||
|
||||
EXPORT int iaxc_get_filters(void)
|
||||
{
|
||||
return iaxci_filters;
|
||||
}
|
||||
|
||||
EXPORT void iaxc_set_filters(int filters)
|
||||
{
|
||||
iaxci_filters = filters;
|
||||
set_speex_filters();
|
||||
}
|
||||
|
||||
EXPORT void iaxc_set_silence_threshold(float thr)
|
||||
{
|
||||
iaxci_silence_threshold = thr;
|
||||
set_speex_filters();
|
||||
}
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_ENCODE_H
|
||||
#define _AUDIO_ENCODE_H
|
||||
|
||||
/* Minimum dB possible in the iaxclient world. This level
|
||||
* is intended to represent silence.
|
||||
*/
|
||||
#define AUDIO_ENCODE_SILENCE_DB -99.0f
|
||||
|
||||
struct iaxc_call;
|
||||
struct iax_event;
|
||||
|
||||
int audio_send_encoded_audio(struct iaxc_call * most_recent_answer, int callNo,
|
||||
void * data, int iEncodeType, int samples);
|
||||
|
||||
int audio_decode_audio(struct iaxc_call * p, void * out, void * data, int len,
|
||||
int iEncodeType, int * samples);
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* iaxclient_lib: An Inter-Asterisk eXchange communication library
|
||||
*
|
||||
* Module: audio_file
|
||||
* Purpose: Audio code to read/write to files
|
||||
* based on audio_portaudio, originally Developed by: Shawn Lawrence, Terrace Communications Inc.
|
||||
* Developed by: Steve Kann
|
||||
* Creation Date: October 30, 2003
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*
|
||||
* IAX library Copyright (c) 2001 Linux Support Services
|
||||
* IAXlib is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*
|
||||
* This library uses the PortAudio Portable Audio Library
|
||||
* For more information see: http://www.portaudio.com
|
||||
* PortAudio Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iaxclient_lib.h"
|
||||
|
||||
typedef short SAMPLE;
|
||||
|
||||
static FILE *inFile=NULL, *outFile=NULL;
|
||||
|
||||
#define FRAMES_PER_BUFFER 80 /* 80 frames == 10ms */
|
||||
|
||||
|
||||
static int file_play_sound(struct iaxc_sound *inSound, int ring) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int file_stop_sound(int soundID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int file_start (struct iaxc_audio_driver *d ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int file_stop (struct iaxc_audio_driver *d ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not used
|
||||
static void file_shutdown_audio() {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
static int file_input(struct iaxc_audio_driver *d, void *samples, int *nSamples) {
|
||||
*nSamples = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int file_output(struct iaxc_audio_driver *d, void *samples, int nSamples) {
|
||||
|
||||
if(outFile) {
|
||||
fwrite(samples, sizeof(SAMPLE), nSamples, outFile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int file_select_devices (struct iaxc_audio_driver *d, int input, int output, int ring) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int file_selected_devices (struct iaxc_audio_driver *d, int *input, int *output, int *ring) {
|
||||
*input = 0;
|
||||
*output = 0;
|
||||
*ring = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int file_destroy (struct iaxc_audio_driver *d )
|
||||
{
|
||||
/* TODO: something should happen here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float file_input_level_get(struct iaxc_audio_driver *d){
|
||||
return -1;
|
||||
}
|
||||
|
||||
static float file_output_level_get(struct iaxc_audio_driver *d){
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int file_input_level_set(struct iaxc_audio_driver *d, float level){
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int file_output_level_set(struct iaxc_audio_driver *d, float level){
|
||||
return -1;
|
||||
}
|
||||
|
||||
EXPORT int iaxc_set_files(FILE *input, FILE *output) {
|
||||
inFile = input;
|
||||
outFile = output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* initialize audio driver */
|
||||
int file_initialize (struct iaxc_audio_driver *d , int sample_rate) {
|
||||
|
||||
if(sample_rate != 8000 ) return -1;
|
||||
|
||||
/* setup methods */
|
||||
d->initialize = file_initialize;
|
||||
d->destroy = file_destroy;
|
||||
d->select_devices = file_select_devices;
|
||||
d->selected_devices = file_selected_devices;
|
||||
d->start = file_start;
|
||||
d->stop = file_stop;
|
||||
d->output = file_output;
|
||||
d->input = file_input;
|
||||
d->input_level_get = file_input_level_get;
|
||||
d->input_level_set = file_input_level_set;
|
||||
d->output_level_get = file_output_level_get;
|
||||
d->output_level_set = file_output_level_set;
|
||||
d->play_sound = file_play_sound;
|
||||
d->stop_sound = file_stop_sound;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003 HorizonLive.com, (c) 2004, Horizon Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*/
|
||||
#ifndef _AUDIO_FILE_H
|
||||
#define _AUDIO_FILE_H
|
||||
|
||||
int file_initialize(struct iaxc_audio_driver *d , int sample_rate);
|
||||
|
||||
#endif
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
#include "iaxclient_lib.h"
|
||||
|
||||
// changed by James Turner to use non-prefixed OpenAL include paths,
|
||||
// which is what CMake official FindOpenAL.cmake and the OpenAL-soft Config.cmake
|
||||
// expect to provide. This avoids any pre-processor logic to decide which
|
||||
// prefix is correct.
|
||||
#include <al.h>
|
||||
#include <alc.h>
|
||||
|
||||
struct openal_priv_data
|
||||
{
|
||||
int sample_rate;
|
||||
int num_buffers;
|
||||
int buffers_head;
|
||||
int buffers_tail;
|
||||
int buffers_free;
|
||||
ALuint* buffers;
|
||||
ALCcontext* out_ctx;
|
||||
ALuint source;
|
||||
ALCdevice* in_dev;
|
||||
float input_level;
|
||||
float output_level;
|
||||
};
|
||||
|
||||
static struct iaxc_audio_device device = {
|
||||
"default",
|
||||
IAXC_AD_INPUT | IAXC_AD_OUTPUT | IAXC_AD_RING | IAXC_AD_INPUT_DEFAULT | IAXC_AD_OUTPUT_DEFAULT | IAXC_AD_RING_DEFAULT,
|
||||
0
|
||||
};
|
||||
|
||||
static int openal_error(const char* function, int err)
|
||||
{
|
||||
fprintf(stderr, "OpenAl function %s failed with code %d\n", function, err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int openal_input(struct iaxc_audio_driver *d, void *samples, int *nSamples)
|
||||
{
|
||||
int err;
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
|
||||
ALCint available;
|
||||
ALCsizei request;
|
||||
|
||||
alcGetIntegerv(priv->in_dev, ALC_CAPTURE_SAMPLES, sizeof(available), &available);
|
||||
/* do not return less data than caller wanted, iaxclient does not like it */
|
||||
request = (available < *nSamples) ? 0 : *nSamples;
|
||||
if (request > 0)
|
||||
{
|
||||
err = alcGetError(priv->in_dev);
|
||||
alcCaptureSamples(priv->in_dev, samples, request);
|
||||
err = alcGetError(priv->in_dev);
|
||||
if (err)
|
||||
{
|
||||
openal_error("alcCaptureSamples", err);
|
||||
*nSamples = 0;
|
||||
return 1;
|
||||
}
|
||||
// software mute, but keep data flowing for sync purposes
|
||||
if (priv->input_level == 0)
|
||||
{
|
||||
memset(samples, 0, 2 * request);
|
||||
}
|
||||
}
|
||||
*nSamples = request;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void openal_unqueue(struct openal_priv_data* priv)
|
||||
{
|
||||
int i;
|
||||
ALint err;
|
||||
ALint processed;
|
||||
|
||||
alGetSourcei(priv->source, AL_BUFFERS_PROCESSED, &processed);
|
||||
|
||||
#ifdef OPENAL_DEBUG
|
||||
{
|
||||
ALint queued;
|
||||
ALint state;
|
||||
|
||||
alGetSourcei(priv->source, AL_BUFFERS_QUEUED, &queued);
|
||||
alGetSourcei(priv->source, AL_SOURCE_STATE, &state);
|
||||
|
||||
fprintf(stderr, "free: %d processed: %d queued: %d head: %d tail: %d state: %d\n",
|
||||
priv->buffers_free, processed, queued, priv->buffers_head, priv->buffers_tail, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
alGetError();
|
||||
for(i = 0; i < processed; i++)
|
||||
{
|
||||
alSourceUnqueueBuffers(priv->source, 1, priv->buffers + priv->buffers_tail);
|
||||
err = alGetError();
|
||||
if (err)
|
||||
{
|
||||
openal_error("alSourceUnqueueBuffers", err);
|
||||
break;
|
||||
}
|
||||
if (++priv->buffers_tail >= priv->num_buffers)
|
||||
{
|
||||
priv->buffers_tail = 0;
|
||||
}
|
||||
++priv->buffers_free;
|
||||
}
|
||||
}
|
||||
|
||||
int openal_output(struct iaxc_audio_driver *d, void *samples, int nSamples)
|
||||
{
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
|
||||
openal_unqueue(priv);
|
||||
/* If we run out of buffers, wait for an arbitrary number to become free */
|
||||
if (priv->buffers_free == 0)
|
||||
{
|
||||
while(priv->buffers_free < 4)
|
||||
{
|
||||
iaxc_millisleep(100);
|
||||
openal_unqueue(priv);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->buffers_free > 0)
|
||||
{
|
||||
ALuint buffer = priv->buffers[priv->buffers_head++];
|
||||
if (priv->buffers_head >= priv->num_buffers)
|
||||
{
|
||||
priv->buffers_head = 0;
|
||||
}
|
||||
|
||||
alBufferData(buffer, AL_FORMAT_MONO16, samples, nSamples * 2, priv->sample_rate);
|
||||
alSourceQueueBuffers(priv->source, 1, &buffer);
|
||||
--priv->buffers_free;
|
||||
|
||||
/* delay start of output until we have 2 buffers */
|
||||
if (priv->buffers_free == priv->num_buffers - 2)
|
||||
{
|
||||
ALint state;
|
||||
|
||||
alGetSourcei(priv->source, AL_SOURCE_STATE, &state);
|
||||
if (state != AL_PLAYING)
|
||||
{
|
||||
#ifdef OPENAL_DEBUG
|
||||
fprintf(stderr, "calling alSourcePlay\n");
|
||||
#endif
|
||||
alSourcePlay(priv->source);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "openal_output buffer overflow\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openal_select_devices(struct iaxc_audio_driver *d, int input, int output, int ring)
|
||||
{
|
||||
return (input != 0 || output !=0 || ring != 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
int openal_selected_devices(struct iaxc_audio_driver *d, int *input, int *output, int *ring)
|
||||
{
|
||||
*input = 0;
|
||||
*output = 0;
|
||||
*ring = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Apparently iaxclient calls openal_start a gazillion times and doesn't call openal_stop.
|
||||
So let's just make them no-ops.
|
||||
*/
|
||||
int openal_start(struct iaxc_audio_driver *d)
|
||||
{
|
||||
int iret = 0;
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
if (priv) /* just to stop compiler noise */
|
||||
iret = 0;
|
||||
return iret;
|
||||
}
|
||||
|
||||
int openal_stop(struct iaxc_audio_driver *d)
|
||||
{
|
||||
int iret = 0;
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
if (priv) /* just to stop compiler noise */
|
||||
iret = 0;
|
||||
return iret;
|
||||
}
|
||||
|
||||
float openal_input_level_get(struct iaxc_audio_driver *d)
|
||||
{
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
|
||||
return priv->input_level;
|
||||
}
|
||||
|
||||
float openal_output_level_get(struct iaxc_audio_driver *d)
|
||||
{
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
|
||||
return priv->output_level;
|
||||
}
|
||||
|
||||
int openal_input_level_set(struct iaxc_audio_driver *d, float level)
|
||||
{
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
priv->input_level = (level < 0.5) ? 0 : 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openal_output_level_set(struct iaxc_audio_driver *d, float level)
|
||||
{
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
priv->output_level = level;
|
||||
alSourcef(priv->source, AL_GAIN, level);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openal_play_sound(struct iaxc_sound *s, int ring)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openal_stop_sound(int id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openal_mic_boost_get(struct iaxc_audio_driver *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openal_mic_boost_set(struct iaxc_audio_driver *d, int enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openal_destroy(struct iaxc_audio_driver *d)
|
||||
{
|
||||
struct openal_priv_data* priv = (struct openal_priv_data*)(d->priv);
|
||||
|
||||
|
||||
alcCaptureStop(priv->in_dev);
|
||||
alcCaptureCloseDevice(priv->in_dev);
|
||||
alDeleteSources(1, &priv->source);
|
||||
|
||||
// FlightGear: added by James to avoid a warning from OpenAL-soft
|
||||
// when we destroy the context in SGSoundMgr_OpenAL: since we
|
||||
// genBuffers below, we should balance that out.
|
||||
alDeleteBuffers(priv->num_buffers, priv->buffers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openal_initialize(struct iaxc_audio_driver *d, int sample_rate)
|
||||
{
|
||||
struct openal_priv_data* priv = malloc(sizeof(struct openal_priv_data));
|
||||
int err = alGetError();
|
||||
d->priv = priv;
|
||||
|
||||
// First we are looking for output device
|
||||
priv->out_ctx = alcGetCurrentContext();
|
||||
|
||||
if( priv->out_ctx == NULL ) { // FGCom standalone only
|
||||
ALCdevice* out_dev = alcOpenDevice(NULL);
|
||||
if (out_dev == 0) return openal_error("alcOpenDevice", alGetError());
|
||||
|
||||
priv->out_ctx = alcCreateContext(out_dev, 0);
|
||||
if (priv->out_ctx == 0) return openal_error("alcCreateContext", alGetError());
|
||||
}
|
||||
|
||||
alcMakeContextCurrent(priv->out_ctx);
|
||||
if ((err = alGetError())) return openal_error("alcMakeContextCurrent", err);
|
||||
|
||||
// Then we look for input device
|
||||
priv->in_dev = alcCaptureOpenDevice(NULL, 8000, AL_FORMAT_MONO16, 800);
|
||||
if (!priv->in_dev) return openal_error("alcCaptureOpenDevice", alGetError());
|
||||
if ((err = alGetError())) return openal_error("alcCaptureOpenDevice1", alGetError());
|
||||
|
||||
alcCaptureStart(priv->in_dev);
|
||||
if ((err = alGetError())) return openal_error("alcCaptureStart", err);
|
||||
|
||||
priv->sample_rate = sample_rate;
|
||||
priv->num_buffers = 20;
|
||||
priv->input_level = 0;
|
||||
priv->output_level = 1;
|
||||
priv->buffers_head = 0;
|
||||
priv->buffers_tail = 0;
|
||||
priv->buffers_free = priv->num_buffers;
|
||||
priv->buffers = (ALuint*)malloc(sizeof(ALuint) * priv->num_buffers);
|
||||
|
||||
alGenBuffers(priv->num_buffers, priv->buffers);
|
||||
if ((err = alGetError())) return openal_error("alGenBuffers", err);
|
||||
|
||||
alGenSources(1, &priv->source);
|
||||
if ((err = alGetError())) return openal_error("alGenSources", err);
|
||||
|
||||
d->initialize = openal_initialize;
|
||||
d->destroy = openal_destroy;
|
||||
d->select_devices = openal_select_devices;
|
||||
d->selected_devices = openal_selected_devices;
|
||||
d->start = openal_start;
|
||||
d->stop = openal_stop;
|
||||
d->output = openal_output;
|
||||
d->input = openal_input;
|
||||
d->input_level_get = openal_input_level_get;
|
||||
d->input_level_set = openal_input_level_set;
|
||||
d->output_level_get = openal_output_level_get;
|
||||
d->output_level_set = openal_output_level_set;
|
||||
d->mic_boost_get = openal_mic_boost_get;
|
||||
d->mic_boost_set = openal_mic_boost_set;
|
||||
d->play_sound = openal_play_sound;
|
||||
d->stop_sound = openal_stop_sound;
|
||||
d->nDevices = 1;
|
||||
d->devices = &device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#ifndef _AUDIO_OPENAL_H
|
||||
#define _AUDIO_OPENAL_H
|
||||
|
||||
int openal_initialize();
|
||||
|
||||
#endif
|
||||
+1158
File diff suppressed because it is too large
Load Diff
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_PORTAUDIO_H
|
||||
#define _AUDIO_PORTAUDIO_H
|
||||
|
||||
#include "iaxclient_lib.h"
|
||||
|
||||
/* normal initialization */
|
||||
int pa_initialize (struct iaxc_audio_driver *d, int sr);
|
||||
|
||||
/* faster initialization which defers initialization of mixers and levels
|
||||
until the device is started */
|
||||
int pa_initialize_deferred (struct iaxc_audio_driver *d, int sr);
|
||||
|
||||
#endif
|
||||
Vendored
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2004 Cyril VELTER
|
||||
*
|
||||
* Contributors:
|
||||
* Cyril VELTER <cyril.velter@metadys.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#include "codec_alaw.h"
|
||||
#include "iaxclient_lib.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define INLINE __inline
|
||||
#else
|
||||
#define INLINE inline
|
||||
#endif
|
||||
|
||||
struct state {
|
||||
plc_state_t plc;
|
||||
};
|
||||
|
||||
static INLINE short int alawdecode (unsigned char alaw)
|
||||
{
|
||||
int value;
|
||||
int segment;
|
||||
|
||||
/* Mask value */
|
||||
alaw ^= 0x55;
|
||||
|
||||
/* Extract and scale value */
|
||||
value = (alaw & 0x0f) << 4;
|
||||
|
||||
/* Extract segment number */
|
||||
segment = (alaw & 0x70) >> 4;
|
||||
|
||||
/* Compute value */
|
||||
switch (segment) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
value += 0x100;
|
||||
break;
|
||||
default:
|
||||
value += 0x100;
|
||||
value <<= segment - 1;
|
||||
}
|
||||
|
||||
/* Extract sign */
|
||||
return (alaw & 0x80) ? value : -value;
|
||||
}
|
||||
|
||||
static INLINE unsigned char alawencode (short int linear)
|
||||
{
|
||||
int mask = 0x55;
|
||||
int segment;
|
||||
unsigned char alaw;
|
||||
|
||||
static int segments[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
|
||||
|
||||
if (linear >= 0)
|
||||
{
|
||||
/* Sign (7th) bit = 1 */
|
||||
mask |= 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sign (7th) bit = 0 */
|
||||
linear = -linear;
|
||||
}
|
||||
|
||||
/* Find the segment */
|
||||
for (segment = 0;segment < 8;segment++)
|
||||
if (linear <= segments[segment])
|
||||
break;
|
||||
|
||||
/* Combine the sign, segment, and quantization bits. */
|
||||
|
||||
if (segment < 8)
|
||||
{
|
||||
if (segment < 2)
|
||||
alaw = (linear >> 4) & 0x0F;
|
||||
else
|
||||
alaw = (linear >> (segment + 3)) & 0x0F;
|
||||
|
||||
return ((alaw | (segment << 4)) ^ mask);
|
||||
}
|
||||
else
|
||||
/* out of range, return maximum value. */
|
||||
return (0x7F ^ mask);
|
||||
}
|
||||
|
||||
static int decode ( struct iaxc_audio_codec *c,
|
||||
int *inlen, unsigned char *in, int *outlen, short *out ) {
|
||||
struct state *state = (struct state *)(c->decstate);
|
||||
short *orig_out = out;
|
||||
short sample;
|
||||
|
||||
|
||||
if(*inlen == 0) {
|
||||
int interp_len = 160;
|
||||
if(*outlen < interp_len) interp_len = *outlen;
|
||||
plc_fillin(&state->plc,out,interp_len);
|
||||
*outlen -= interp_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
while ((*inlen > 0) && (*outlen > 0)) {
|
||||
sample = alawdecode((unsigned char)*(in++));
|
||||
*(out++) = sample;
|
||||
(*inlen)--; (*outlen)--;
|
||||
}
|
||||
plc_rx(&state->plc, orig_out, (int)(out - orig_out));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encode ( struct iaxc_audio_codec *c,
|
||||
int *inlen, short *in, int *outlen, unsigned char *out ) {
|
||||
|
||||
while ((*inlen > 0) && (*outlen > 0)) {
|
||||
*(out++) = alawencode(*(in++));
|
||||
(*inlen)--; (*outlen)--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy ( struct iaxc_audio_codec *c) {
|
||||
free(c);
|
||||
}
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_alaw_new() {
|
||||
|
||||
struct iaxc_audio_codec *c = (struct iaxc_audio_codec *)calloc(1, sizeof(struct iaxc_audio_codec));
|
||||
|
||||
if(!c) return c;
|
||||
|
||||
strcpy(c->name,"alaw");
|
||||
c->format = IAXC_FORMAT_ALAW;
|
||||
c->encode = encode;
|
||||
c->decode = decode;
|
||||
c->destroy = destroy;
|
||||
|
||||
/* really, we can use less, but don't want to */
|
||||
c->minimum_frame_size = 160;
|
||||
|
||||
/* decoder state, used for interpolation */
|
||||
c->decstate = calloc(sizeof(struct state),1);
|
||||
plc_init(&((struct state *)c->decstate)->plc);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2004 Cyril VELTER
|
||||
*
|
||||
* Contributors:
|
||||
* Cyril VELTER <cyril.velter@metadys.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_alaw_new();
|
||||
+748
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
* Peter Grayson <jpgrayson@gmail.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*
|
||||
* A video codec using the ffmpeg library.
|
||||
*
|
||||
* TODO: this code still uses its own slicing mechanism
|
||||
* It should be converted to use the API provided in slice.[ch]
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "codec_ffmpeg.h"
|
||||
#include "iaxclient_lib.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "libavcodec/avcodec.h"
|
||||
#else
|
||||
#include <ffmpeg/avcodec.h>
|
||||
#endif
|
||||
|
||||
struct slice_header_t
|
||||
{
|
||||
unsigned char version;
|
||||
unsigned short source_id;
|
||||
unsigned char frame_index;
|
||||
unsigned char slice_index;
|
||||
unsigned char num_slices;
|
||||
};
|
||||
|
||||
struct encoder_ctx
|
||||
{
|
||||
AVCodecContext * avctx;
|
||||
AVFrame * picture;
|
||||
|
||||
struct slice_header_t slice_header;
|
||||
|
||||
unsigned char *frame_buf;
|
||||
int frame_buf_len;
|
||||
};
|
||||
|
||||
struct decoder_ctx
|
||||
{
|
||||
AVCodecContext * avctx;
|
||||
AVFrame * picture;
|
||||
|
||||
struct slice_header_t slice_header;
|
||||
int frame_size;
|
||||
|
||||
unsigned char * frame_buf;
|
||||
int frame_buf_len;
|
||||
};
|
||||
|
||||
static struct slice_set_t * g_slice_set = 0;
|
||||
|
||||
static enum CodecID map_iaxc_codec_to_avcodec(int format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case IAXC_FORMAT_H261:
|
||||
return CODEC_ID_H261;
|
||||
|
||||
case IAXC_FORMAT_H263:
|
||||
return CODEC_ID_H263;
|
||||
|
||||
case IAXC_FORMAT_H263_PLUS:
|
||||
return CODEC_ID_H263P;
|
||||
|
||||
case IAXC_FORMAT_MPEG4:
|
||||
return CODEC_ID_MPEG4;
|
||||
|
||||
case IAXC_FORMAT_H264:
|
||||
return CODEC_ID_H264;
|
||||
|
||||
case IAXC_FORMAT_THEORA:
|
||||
return CODEC_ID_THEORA;
|
||||
|
||||
default:
|
||||
return CODEC_ID_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy(struct iaxc_video_codec *c)
|
||||
{
|
||||
if (c)
|
||||
{
|
||||
struct encoder_ctx *e = (struct encoder_ctx *) c->encstate;
|
||||
struct decoder_ctx *d = (struct decoder_ctx *) c->decstate;
|
||||
|
||||
if (e)
|
||||
{
|
||||
av_freep(&e->avctx);
|
||||
av_freep(&e->picture);
|
||||
if (e->frame_buf)
|
||||
free(e->frame_buf);
|
||||
free(e);
|
||||
}
|
||||
|
||||
if (d)
|
||||
{
|
||||
av_freep(&d->avctx);
|
||||
av_freep(&d->picture);
|
||||
if (d->frame_buf)
|
||||
free(d->frame_buf);
|
||||
free(d);
|
||||
}
|
||||
|
||||
free(c);
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_decoder_frame_state(struct decoder_ctx * d)
|
||||
{
|
||||
memset(d->frame_buf, 0, d->frame_buf_len);
|
||||
d->frame_size = 0;
|
||||
d->slice_header.slice_index = 0;
|
||||
}
|
||||
|
||||
static int frame_to_frame_xlate(AVCodecContext * avctx, AVFrame * picture,
|
||||
int * outlen, char * out)
|
||||
{
|
||||
int line;
|
||||
|
||||
*outlen = avctx->width * avctx->height * 6 / 4;
|
||||
|
||||
for ( line = 0; line < avctx->height / 2; ++line )
|
||||
{
|
||||
/* y even */
|
||||
memcpy(out + avctx->width * (2 * line + 0),
|
||||
picture->data[0] + (2 * line + 0) * picture->linesize[0],
|
||||
avctx->width);
|
||||
|
||||
/* y odd */
|
||||
memcpy(out + avctx->width * (2 * line + 1),
|
||||
picture->data[0] + (2 * line + 1) * picture->linesize[0],
|
||||
avctx->width);
|
||||
|
||||
/* u + v */
|
||||
memcpy(out + avctx->width * avctx->height
|
||||
+ line * avctx->width / 2,
|
||||
picture->data[1] + line * picture->linesize[1],
|
||||
avctx->width / 2);
|
||||
|
||||
memcpy(out + avctx->width * avctx->height * 5 / 4
|
||||
+ line * avctx->width / 2,
|
||||
picture->data[2] + line * picture->linesize[2],
|
||||
avctx->width / 2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pass_frame_to_decoder(AVCodecContext * avctx, AVFrame * picture,
|
||||
int inlen, unsigned char * in, int * outlen, char * out)
|
||||
{
|
||||
int bytes_decoded;
|
||||
int got_picture;
|
||||
|
||||
bytes_decoded = avcodec_decode_video(avctx, picture, &got_picture,
|
||||
in, inlen);
|
||||
|
||||
if ( bytes_decoded != inlen )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"codec_ffmpeg: decode: failed to decode whole frame %d / %d\n",
|
||||
bytes_decoded, inlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( !got_picture )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"codec_ffmpeg: decode: failed to get picture\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
frame_to_frame_xlate(avctx, picture, outlen, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *parse_slice_header(char * in, struct slice_header_t * slice_header)
|
||||
{
|
||||
slice_header->version = in[0];
|
||||
slice_header->source_id = (in[1] << 8) | in[2];
|
||||
slice_header->frame_index = in[3];
|
||||
slice_header->slice_index = in[4];
|
||||
slice_header->num_slices = in[5];
|
||||
|
||||
if ( slice_header->version != 0 )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"codec_ffmpeg: decode: unknown slice header version %d\n",
|
||||
slice_header->version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return in + 6;
|
||||
}
|
||||
|
||||
static int decode_iaxc_slice(struct iaxc_video_codec * c, int inlen,
|
||||
char * in, int * outlen, char * out)
|
||||
{
|
||||
struct decoder_ctx *d = (struct decoder_ctx *) c->decstate;
|
||||
struct slice_header_t * sh_saved = &d->slice_header;
|
||||
struct slice_header_t sh_this;
|
||||
char * inp;
|
||||
int ret;
|
||||
|
||||
inp = parse_slice_header(in, &sh_this);
|
||||
|
||||
if ( !inp )
|
||||
return -1;
|
||||
|
||||
inlen -= inp - in;
|
||||
|
||||
if ( sh_this.source_id == sh_saved->source_id )
|
||||
{
|
||||
unsigned char frame_delta;
|
||||
|
||||
frame_delta = sh_this.frame_index - sh_saved->frame_index;
|
||||
|
||||
if ( frame_delta > 20 )
|
||||
{
|
||||
/* This is an old slice. It's too late, we ignore it. */
|
||||
return 1;
|
||||
}
|
||||
else if ( frame_delta > 0 )
|
||||
{
|
||||
/* This slice belongs to a future frame */
|
||||
if ( sh_saved->slice_index > 0 )
|
||||
{
|
||||
/* We have received slices for a previous
|
||||
* frame (e.g. the one we were previously
|
||||
* working on), so we go ahead and send this
|
||||
* partial frame to the decoder and get setup
|
||||
* for the new frame.
|
||||
*/
|
||||
|
||||
ret = pass_frame_to_decoder(d->avctx, d->picture,
|
||||
d->frame_size, d->frame_buf,
|
||||
outlen, out);
|
||||
|
||||
reset_decoder_frame_state(d);
|
||||
|
||||
if ( ret )
|
||||
return -1;
|
||||
}
|
||||
|
||||
sh_saved->frame_index = sh_this.frame_index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_saved->source_id = sh_this.source_id;
|
||||
sh_saved->frame_index = sh_this.frame_index;
|
||||
sh_saved->slice_index = 0;
|
||||
d->frame_size = 0;
|
||||
}
|
||||
|
||||
if ( c->fragsize * sh_this.slice_index + inlen > d->frame_buf_len )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"codec_ffmpeg: decode: slice overflows decoder frame buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(d->frame_buf + c->fragsize * sh_this.slice_index,
|
||||
inp, inlen);
|
||||
sh_saved->slice_index++;
|
||||
d->frame_size = c->fragsize * sh_this.slice_index + inlen;
|
||||
|
||||
if ( sh_saved->slice_index < sh_this.num_slices )
|
||||
{
|
||||
/* Do not decode yet, there are more slices coming for
|
||||
* this frame.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = pass_frame_to_decoder(d->avctx, d->picture, d->frame_size,
|
||||
d->frame_buf, outlen, out);
|
||||
|
||||
reset_decoder_frame_state(d);
|
||||
|
||||
if ( ret )
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_rtp_slice(struct iaxc_video_codec * c,
|
||||
int inlen, char * in, int * outlen, char * out)
|
||||
{
|
||||
struct decoder_ctx *d = (struct decoder_ctx *) c->decstate;
|
||||
int ret = 1;
|
||||
|
||||
while ( inlen )
|
||||
{
|
||||
int bytes_decoded;
|
||||
int got_picture;
|
||||
|
||||
bytes_decoded = avcodec_decode_video(d->avctx, d->picture,
|
||||
&got_picture, (unsigned char *)in, inlen);
|
||||
|
||||
if ( bytes_decoded < 0 )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"codec_ffmpeg: decode: error decoding frame\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
inlen -= bytes_decoded;
|
||||
in += bytes_decoded;
|
||||
|
||||
if ( got_picture && ret == 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"codec_ffmpeg: decode: unexpected second frame\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( got_picture )
|
||||
{
|
||||
frame_to_frame_xlate(d->avctx, d->picture, outlen, out);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void slice_encoded_frame(struct slice_header_t * sh,
|
||||
struct slice_set_t * slice_set,
|
||||
unsigned char * in, int inlen, int fragsize)
|
||||
{
|
||||
sh->num_slices = slice_set->num_slices = (inlen - 1) / fragsize + 1;
|
||||
|
||||
for (sh->slice_index = 0; sh->slice_index < sh->num_slices;
|
||||
++sh->slice_index)
|
||||
{
|
||||
int slice_size = (sh->slice_index == sh->num_slices - 1) ?
|
||||
inlen % fragsize : fragsize;
|
||||
|
||||
slice_set->size[sh->slice_index] = slice_size + 6;
|
||||
slice_set->data[sh->slice_index][0] = sh->version;
|
||||
slice_set->data[sh->slice_index][1] = sh->source_id >> 8;
|
||||
slice_set->data[sh->slice_index][2] = sh->source_id & 0xff;
|
||||
slice_set->data[sh->slice_index][3] = sh->frame_index;
|
||||
slice_set->data[sh->slice_index][4] = sh->slice_index;
|
||||
slice_set->data[sh->slice_index][5] = sh->num_slices;
|
||||
|
||||
memcpy(&slice_set->data[sh->slice_index][6], in, slice_size);
|
||||
|
||||
in += slice_size;
|
||||
}
|
||||
|
||||
sh->frame_index++;
|
||||
}
|
||||
|
||||
static int encode(struct iaxc_video_codec *c,
|
||||
int inlen, char * in, struct slice_set_t * slice_set)
|
||||
{
|
||||
struct encoder_ctx *e = (struct encoder_ctx *) c->encstate;
|
||||
int encoded_size;
|
||||
|
||||
avcodec_get_frame_defaults(e->picture);
|
||||
|
||||
e->picture->data[0] = (unsigned char *)in;
|
||||
e->picture->data[1] = (unsigned char *)in
|
||||
+ e->avctx->width * e->avctx->height;
|
||||
e->picture->data[2] = (unsigned char *)in
|
||||
+ e->avctx->width * e->avctx->height * 5 / 4;
|
||||
|
||||
e->picture->linesize[0] = e->avctx->width;
|
||||
e->picture->linesize[1] = e->avctx->width / 2;
|
||||
e->picture->linesize[2] = e->avctx->width / 2;
|
||||
|
||||
/* TODO: investigate setting a real pts value */
|
||||
e->picture->pts = AV_NOPTS_VALUE;
|
||||
|
||||
/* TODO: investigate quality */
|
||||
e->picture->quality = 10;
|
||||
|
||||
g_slice_set = slice_set;
|
||||
slice_set->num_slices = 0;
|
||||
|
||||
encoded_size = avcodec_encode_video(e->avctx,
|
||||
e->frame_buf, e->frame_buf_len, e->picture);
|
||||
|
||||
if (!encoded_size)
|
||||
{
|
||||
fprintf(stderr, "codec_ffmpeg: encode failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
slice_set->key_frame = e->avctx->coded_frame->key_frame;
|
||||
|
||||
/* This is paranoia, of course. */
|
||||
g_slice_set = 0;
|
||||
|
||||
/* We are in one of two modes here.
|
||||
*
|
||||
* The first possibility is that the codec supports rtp
|
||||
* packetization. In this case, the slice_set has already been
|
||||
* filled via encode_rtp_callback() calls made during the call
|
||||
* to avcodec_encode_video().
|
||||
*
|
||||
* The second possibility is that we have one big encoded frame
|
||||
* that we need to slice-up ourselves.
|
||||
*/
|
||||
|
||||
if (!e->avctx->rtp_payload_size)
|
||||
slice_encoded_frame(&e->slice_header, slice_set,
|
||||
e->frame_buf, encoded_size, c->fragsize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void encode_rtp_callback(struct AVCodecContext *avctx, void *data, int size,
|
||||
int mb_nb)
|
||||
{
|
||||
memcpy(&g_slice_set->data[g_slice_set->num_slices], data, size);
|
||||
g_slice_set->size[g_slice_set->num_slices] = size;
|
||||
g_slice_set->num_slices++;
|
||||
}
|
||||
|
||||
struct iaxc_video_codec *codec_video_ffmpeg_new(int format, int w, int h,
|
||||
int framerate, int bitrate,
|
||||
int fragsize)
|
||||
{
|
||||
struct encoder_ctx *e;
|
||||
struct decoder_ctx *d;
|
||||
AVCodec *codec;
|
||||
int ff_enc_id, ff_dec_id;
|
||||
char *name;
|
||||
|
||||
struct iaxc_video_codec *c = calloc(sizeof(struct iaxc_video_codec), 1);
|
||||
|
||||
if (!c)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"codec_ffmpeg: failed to allocate video context\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
avcodec_init();
|
||||
avcodec_register_all();
|
||||
|
||||
c->format = format;
|
||||
c->width = w;
|
||||
c->height = h;
|
||||
c->framerate = framerate;
|
||||
c->bitrate = bitrate;
|
||||
/* TODO: Is a fragsize of zero valid? If so, there's a divide
|
||||
* by zero error to contend with.
|
||||
*/
|
||||
c->fragsize = fragsize;
|
||||
|
||||
c->encode = encode;
|
||||
c->decode = decode_iaxc_slice;
|
||||
c->destroy = destroy;
|
||||
|
||||
c->encstate = calloc(sizeof(struct encoder_ctx), 1);
|
||||
if (!c->encstate)
|
||||
goto bail;
|
||||
e = c->encstate;
|
||||
e->avctx = avcodec_alloc_context();
|
||||
if (!e->avctx)
|
||||
goto bail;
|
||||
e->picture = avcodec_alloc_frame();
|
||||
if (!e->picture)
|
||||
goto bail;
|
||||
/* The idea here is that the encoded frame that will land in this
|
||||
* buffer will be no larger than the size of an uncompressed 32-bit
|
||||
* rgb frame.
|
||||
*
|
||||
* TODO: Is this assumption really valid?
|
||||
*/
|
||||
e->frame_buf_len = w * h * 4;
|
||||
e->frame_buf = malloc(e->frame_buf_len);
|
||||
if (!e->frame_buf)
|
||||
goto bail;
|
||||
|
||||
c->decstate = calloc(sizeof(struct decoder_ctx), 1);
|
||||
if (!c->decstate)
|
||||
goto bail;
|
||||
d = c->decstate;
|
||||
d->avctx = avcodec_alloc_context();
|
||||
if (!d->avctx)
|
||||
goto bail;
|
||||
d->picture = avcodec_alloc_frame();
|
||||
if (!d->picture)
|
||||
goto bail;
|
||||
d->frame_buf_len = e->frame_buf_len;
|
||||
d->frame_buf = malloc(d->frame_buf_len);
|
||||
if (!d->frame_buf)
|
||||
goto bail;
|
||||
|
||||
e->slice_header.version = 0;
|
||||
srandom(time(0));
|
||||
e->slice_header.source_id = random() & 0xffff;
|
||||
|
||||
e->avctx->time_base.num = 1;
|
||||
e->avctx->time_base.den = framerate;
|
||||
|
||||
e->avctx->width = w;
|
||||
e->avctx->height = h;
|
||||
|
||||
e->avctx->bit_rate = bitrate;
|
||||
|
||||
/* This determines how often i-frames are sent */
|
||||
e->avctx->gop_size = framerate * 3;
|
||||
e->avctx->pix_fmt = PIX_FMT_YUV420P;
|
||||
e->avctx->has_b_frames = 0;
|
||||
|
||||
e->avctx->mb_qmin = e->avctx->qmin = 10;
|
||||
e->avctx->mb_qmax = e->avctx->qmax = 10;
|
||||
|
||||
e->avctx->lmin = 2 * FF_QP2LAMBDA;
|
||||
e->avctx->lmax = 10 * FF_QP2LAMBDA;
|
||||
e->avctx->global_quality = FF_QP2LAMBDA * 2;
|
||||
e->avctx->qblur = 0.5;
|
||||
e->avctx->global_quality = 10;
|
||||
|
||||
e->avctx->flags |= CODEC_FLAG_PSNR;
|
||||
e->avctx->flags |= CODEC_FLAG_QSCALE;
|
||||
|
||||
e->avctx->mb_decision = FF_MB_DECISION_SIMPLE;
|
||||
|
||||
ff_enc_id = ff_dec_id = map_iaxc_codec_to_avcodec(format);
|
||||
|
||||
/* Note, when fragsize is used (non-zero) ffmpeg will use a "best
|
||||
* effort" strategy: the fragment size will be fragsize +/- 20%
|
||||
*/
|
||||
|
||||
switch (format)
|
||||
{
|
||||
|
||||
case IAXC_FORMAT_H261:
|
||||
/* TODO: H261 only works with specific resolutions. */
|
||||
name = "H.261";
|
||||
break;
|
||||
|
||||
case IAXC_FORMAT_H263:
|
||||
/* TODO: H263 only works with specific resolutions. */
|
||||
name = "H.263";
|
||||
e->avctx->flags |= CODEC_FLAG_AC_PRED;
|
||||
if (fragsize)
|
||||
{
|
||||
c->decode = decode_rtp_slice;
|
||||
e->avctx->rtp_payload_size = fragsize;
|
||||
e->avctx->flags |=
|
||||
CODEC_FLAG_TRUNCATED | CODEC_FLAG2_STRICT_GOP;
|
||||
e->avctx->rtp_callback = encode_rtp_callback;
|
||||
d->avctx->flags |= CODEC_FLAG_TRUNCATED;
|
||||
}
|
||||
break;
|
||||
|
||||
case IAXC_FORMAT_H263_PLUS:
|
||||
/* Although the encoder is CODEC_ID_H263P, the decoder
|
||||
* is the regular h.263, so we handle this special case
|
||||
* here.
|
||||
*/
|
||||
ff_dec_id = CODEC_ID_H263;
|
||||
name = "H.263+";
|
||||
e->avctx->flags |= CODEC_FLAG_AC_PRED;
|
||||
if (fragsize)
|
||||
{
|
||||
c->decode = decode_rtp_slice;
|
||||
e->avctx->rtp_payload_size = fragsize;
|
||||
e->avctx->flags |=
|
||||
CODEC_FLAG_TRUNCATED |
|
||||
CODEC_FLAG_H263P_SLICE_STRUCT |
|
||||
CODEC_FLAG2_STRICT_GOP |
|
||||
CODEC_FLAG2_LOCAL_HEADER;
|
||||
e->avctx->rtp_callback = encode_rtp_callback;
|
||||
d->avctx->flags |= CODEC_FLAG_TRUNCATED;
|
||||
}
|
||||
break;
|
||||
|
||||
case IAXC_FORMAT_MPEG4:
|
||||
name = "MPEG4";
|
||||
c->decode = decode_rtp_slice;
|
||||
e->avctx->rtp_payload_size = fragsize;
|
||||
e->avctx->rtp_callback = encode_rtp_callback;
|
||||
e->avctx->flags |=
|
||||
CODEC_FLAG_TRUNCATED |
|
||||
CODEC_FLAG_H263P_SLICE_STRUCT |
|
||||
CODEC_FLAG2_STRICT_GOP |
|
||||
CODEC_FLAG2_LOCAL_HEADER;
|
||||
|
||||
d->avctx->flags |= CODEC_FLAG_TRUNCATED;
|
||||
break;
|
||||
|
||||
case IAXC_FORMAT_H264:
|
||||
name = "H.264";
|
||||
|
||||
/*
|
||||
* Encoder flags
|
||||
*/
|
||||
|
||||
/* Headers are not repeated */
|
||||
/* e->avctx->flags |= CODEC_FLAG_GLOBAL_HEADER; */
|
||||
|
||||
/* Slower, less blocky */
|
||||
/* e->avctx->flags |= CODEC_FLAG_LOOP_FILTER; */
|
||||
|
||||
e->avctx->flags |= CODEC_FLAG_PASS1;
|
||||
/* e->avctx->flags |= CODEC_FLAG_PASS2; */
|
||||
|
||||
/* Compute psnr values at encode-time (avctx->error[]) */
|
||||
/* e->avctx->flags |= CODEC_FLAG_PSNR; */
|
||||
|
||||
/* e->avctx->flags2 |= CODEC_FLAG2_8X8DCT; */
|
||||
|
||||
/* Access Unit Delimiters */
|
||||
e->avctx->flags2 |= CODEC_FLAG2_AUD;
|
||||
|
||||
/* Allow b-frames to be used as reference */
|
||||
/* e->avctx->flags2 |= CODEC_FLAG2_BPYRAMID; */
|
||||
|
||||
/* b-frame rate distortion optimization */
|
||||
/* e->avctx->flags2 |= CODEC_FLAG2_BRDO; */
|
||||
|
||||
/* e->avctx->flags2 |= CODEC_FLAG2_FASTPSKIP; */
|
||||
|
||||
/* Multiple references per partition */
|
||||
/* e->avctx->flags2 |= CODEC_FLAG2_MIXED_REFS; */
|
||||
|
||||
/* Weighted biprediction for b-frames */
|
||||
/* e->avctx->flags2 |= CODEC_FLAG2_WPRED; */
|
||||
|
||||
/*
|
||||
* Decoder flags
|
||||
*/
|
||||
|
||||
/* Do not draw edges */
|
||||
/* d->avctx->flags |= CODEC_FLAG_EMU_EDGE; */
|
||||
|
||||
/* Decode grayscale only */
|
||||
/* d->avctx->flags |= CODEC_FLAG_GRAY; */
|
||||
|
||||
/* d->avctx->flags |= CODEC_FLAG_LOW_DELAY; */
|
||||
|
||||
/* Allow input bitstream to be randomly truncated */
|
||||
/* d->avctx->flags |= CODEC_FLAG_TRUNCATED; */
|
||||
|
||||
/* Allow out-of-spec speed tricks */
|
||||
/* d->avctx->flags2 |= CODEC_FLAG2_FAST; */
|
||||
break;
|
||||
|
||||
case IAXC_FORMAT_THEORA:
|
||||
/* TODO: ffmpeg only has a theora decoder. Until it has
|
||||
* an encoder also, we cannot use ffmpeg for theora.
|
||||
*/
|
||||
name = "Theora";
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "codec_ffmpeg: unsupported format (0x%08x)\n",
|
||||
format);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
strcpy(c->name, "ffmpeg-");
|
||||
strncat(c->name, name, sizeof(c->name));
|
||||
|
||||
/* Get the codecs */
|
||||
codec = avcodec_find_encoder(ff_enc_id);
|
||||
if (!codec)
|
||||
{
|
||||
iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
|
||||
"codec_ffmpeg: cannot find encoder %d\n",
|
||||
ff_enc_id);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (avcodec_open(e->avctx, codec))
|
||||
{
|
||||
iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
|
||||
"codec_ffmpeg: cannot open encoder %s\n", name);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
codec = avcodec_find_decoder(ff_dec_id);
|
||||
if (!codec)
|
||||
{
|
||||
iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
|
||||
"codec_ffmpeg: cannot find decoder %d\n",
|
||||
ff_dec_id);
|
||||
goto bail;
|
||||
}
|
||||
if (avcodec_open(d->avctx, codec))
|
||||
{
|
||||
iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
|
||||
"codec_ffmpeg: cannot open decoder %s\n", name);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
{
|
||||
enum PixelFormat fmts[] = { PIX_FMT_YUV420P, -1 };
|
||||
if (d->avctx->get_format(d->avctx, fmts) != PIX_FMT_YUV420P)
|
||||
{
|
||||
iaxci_usermsg(IAXC_TEXT_TYPE_ERROR,
|
||||
"codec_ffmpeg: cannot set decode format to YUV420P\n");
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
|
||||
bail:
|
||||
destroy(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int codec_video_ffmpeg_check_codec(int format)
|
||||
{
|
||||
AVCodec *codec;
|
||||
enum CodecID codec_id;
|
||||
|
||||
/* These functions are idempotent, so it is okay that we
|
||||
* may call them elsewhere at a different time.
|
||||
*/
|
||||
avcodec_init();
|
||||
avcodec_register_all();
|
||||
|
||||
codec_id = map_iaxc_codec_to_avcodec(format);
|
||||
|
||||
if (codec_id == CODEC_ID_NONE)
|
||||
return 0;
|
||||
|
||||
codec = avcodec_find_encoder(codec_id);
|
||||
|
||||
return codec ? 1 : 0;
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
* Peter Grayson <jpgrayson@gmail.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*
|
||||
* A video codec using the ffmpeg library.
|
||||
*/
|
||||
|
||||
struct iaxc_video_codec *codec_video_ffmpeg_new(int format, int w, int h, int framerate, int bitrate, int fragsize);
|
||||
|
||||
int codec_video_ffmpeg_check_codec(int format);
|
||||
Vendored
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#include "codec_gsm.h"
|
||||
#include "iaxclient_lib.h"
|
||||
#include "gsm.h"
|
||||
|
||||
struct state {
|
||||
gsm gsmstate;
|
||||
plc_state_t plc;
|
||||
};
|
||||
|
||||
|
||||
static void destroy ( struct iaxc_audio_codec *c) {
|
||||
|
||||
struct state * encstate = (struct state *) c->encstate;
|
||||
struct state * decstate = (struct state *) c->decstate;
|
||||
|
||||
gsm_destroy(encstate->gsmstate);
|
||||
gsm_destroy(decstate->gsmstate);
|
||||
free(c->encstate);
|
||||
free(c->decstate);
|
||||
free(c);
|
||||
}
|
||||
|
||||
|
||||
static int decode ( struct iaxc_audio_codec *c,
|
||||
int *inlen, unsigned char *in, int *outlen, short *out ) {
|
||||
struct state * decstate = (struct state *) c->decstate;
|
||||
|
||||
/* use generic interpolation */
|
||||
if(*inlen == 0) {
|
||||
int interp_len = 160;
|
||||
if(*outlen < interp_len) interp_len = *outlen;
|
||||
plc_fillin(&decstate->plc,out,interp_len);
|
||||
*outlen -= interp_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* need to decode minimum of 33 bytes to 160 byte output */
|
||||
while( (*inlen >= 33) && (*outlen >= 160) ) {
|
||||
if(gsm_decode(decstate->gsmstate, in, out))
|
||||
{
|
||||
fprintf(stderr, "codec_gsm: gsm_decode returned error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* push decoded data to interpolation buffer */
|
||||
plc_rx(&decstate->plc,out,160);
|
||||
|
||||
/* we used 33 bytes of input, and 160 bytes of output */
|
||||
*inlen -= 33;
|
||||
in += 33;
|
||||
*outlen -= 160;
|
||||
out += 160;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encode ( struct iaxc_audio_codec *c,
|
||||
int *inlen, short *in, int *outlen, unsigned char *out ) {
|
||||
|
||||
struct state * encstate = (struct state *) c->encstate;
|
||||
|
||||
|
||||
/* need to encode minimum of 160 bytes to 33 byte output */
|
||||
while( (*inlen >= 160) && (*outlen >= 33) ) {
|
||||
gsm_encode(encstate->gsmstate, in, out);
|
||||
|
||||
/* we used 160 bytes of input, and 33 bytes of output */
|
||||
*inlen -= 160;
|
||||
in += 160;
|
||||
*outlen -= 33;
|
||||
out += 33;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_gsm_new() {
|
||||
|
||||
struct state * encstate;
|
||||
struct state * decstate;
|
||||
struct iaxc_audio_codec *c = (struct iaxc_audio_codec *)calloc(sizeof(struct iaxc_audio_codec),1);
|
||||
|
||||
|
||||
if(!c) return c;
|
||||
|
||||
strcpy(c->name,"gsm 06.10");
|
||||
c->format = IAXC_FORMAT_GSM;
|
||||
c->encode = encode;
|
||||
c->decode = decode;
|
||||
c->destroy = destroy;
|
||||
|
||||
c->minimum_frame_size = 160;
|
||||
|
||||
c->encstate = calloc(sizeof(struct state),1);
|
||||
c->decstate = calloc(sizeof(struct state),1);
|
||||
|
||||
/* leaks a bit on no-memory */
|
||||
if(!(c->encstate && c->decstate))
|
||||
return NULL;
|
||||
|
||||
encstate = (struct state *) c->encstate;
|
||||
decstate = (struct state *) c->decstate;
|
||||
|
||||
encstate->gsmstate = gsm_create();
|
||||
decstate->gsmstate = gsm_create();
|
||||
|
||||
if(!(encstate->gsmstate && decstate->gsmstate))
|
||||
return NULL;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_gsm_new();
|
||||
Vendored
+115
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#include "codec_ilbc.h"
|
||||
#include "iaxclient_lib.h"
|
||||
#include "iLBC/iLBC_encode.h"
|
||||
#include "iLBC/iLBC_decode.h"
|
||||
|
||||
|
||||
static void destroy ( struct iaxc_audio_codec *c) {
|
||||
free(c->encstate);
|
||||
free(c->decstate);
|
||||
free(c);
|
||||
}
|
||||
|
||||
|
||||
static int decode ( struct iaxc_audio_codec *c,
|
||||
int *inlen, char *in, int *outlen, short *out ) {
|
||||
|
||||
float fbuf[240];
|
||||
int i;
|
||||
|
||||
if(*inlen == 0) {
|
||||
//fprintf(stderr, "ILBC Interpolate\n");
|
||||
iLBC_decode(fbuf, NULL, c->decstate, 0);
|
||||
for(i=0;i<240;i++)
|
||||
out[i] = fbuf[i];
|
||||
*outlen -= 240;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* need to decode minimum of 33 bytes to 160 byte output */
|
||||
if( (*inlen < 50) || (*outlen < 240) ) {
|
||||
fprintf(stderr, "codec_ilbc: inlen = %d outlen= %d\n",*inlen,*outlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while( (*inlen >= 50) && (*outlen >= 240) ) {
|
||||
iLBC_decode(fbuf, in, c->decstate, 1);
|
||||
for(i=0;i<240;i++)
|
||||
out[i] = fbuf[i];
|
||||
|
||||
out += 240;
|
||||
*outlen -= 240;
|
||||
in += 50;
|
||||
*inlen -= 50;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encode ( struct iaxc_audio_codec *c,
|
||||
int *inlen, short *in, int *outlen, char *out ) {
|
||||
|
||||
float fbuf[240];
|
||||
int i;
|
||||
|
||||
while( (*inlen >= 240) && (*outlen >= 50) ) {
|
||||
|
||||
for(i=0;i<240;i++)
|
||||
fbuf[i] = in[i];
|
||||
|
||||
iLBC_encode(out,fbuf, c->encstate);
|
||||
|
||||
out += 50;
|
||||
*outlen -= 50;
|
||||
in += 240;
|
||||
*inlen -= 240;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_ilbc_new() {
|
||||
struct iaxc_audio_codec *c = calloc(sizeof(struct iaxc_audio_codec),1);
|
||||
|
||||
|
||||
if(!c) return c;
|
||||
|
||||
strcpy(c->name,"iLBC");
|
||||
c->format = IAXC_FORMAT_ILBC;
|
||||
c->encode = encode;
|
||||
c->decode = decode;
|
||||
c->destroy = destroy;
|
||||
|
||||
c->minimum_frame_size = 240;
|
||||
|
||||
c->encstate = calloc(sizeof(iLBC_Enc_Inst_t),1);
|
||||
c->decstate = calloc(sizeof(iLBC_Dec_Inst_t),1);
|
||||
|
||||
/* leaks a bit on no-memory */
|
||||
if(!(c->encstate && c->decstate))
|
||||
return NULL;
|
||||
|
||||
/* the 30 parameters are used for the latest iLBC sources, in
|
||||
* http://www.ietf.org/internet-drafts/draft-ietf-avt-ilbc-codec-05.txt
|
||||
* as used in asterisk-CVS as of 14 Oct 2004 */
|
||||
initEncode(c->encstate, 30);
|
||||
initDecode(c->decstate, 30, 1); /* use enhancer */
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_ilbc_new();
|
||||
Vendored
+190
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2004, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#include "codec_speex.h"
|
||||
#include "iaxclient_lib.h"
|
||||
#include "speex/speex.h"
|
||||
|
||||
struct State
|
||||
{
|
||||
void *state;
|
||||
int frame_size;
|
||||
SpeexBits bits;
|
||||
};
|
||||
|
||||
|
||||
static void destroy ( struct iaxc_audio_codec *c)
|
||||
{
|
||||
struct State * encstate = (struct State *) c->encstate;
|
||||
struct State * decstate = (struct State *) c->decstate;
|
||||
|
||||
speex_bits_destroy(&encstate->bits);
|
||||
speex_bits_destroy(&decstate->bits);
|
||||
speex_encoder_destroy(encstate->state);
|
||||
speex_decoder_destroy(decstate->state);
|
||||
|
||||
free(c->encstate);
|
||||
free(c->decstate);
|
||||
|
||||
free(c);
|
||||
}
|
||||
|
||||
|
||||
static int decode( struct iaxc_audio_codec *c,
|
||||
int *inlen, unsigned char *in, int *outlen, short *out )
|
||||
{
|
||||
struct State * decstate = (struct State *) c->decstate;
|
||||
|
||||
if ( *inlen == 0 )
|
||||
{
|
||||
speex_decode_int(decstate->state, NULL, out);
|
||||
*outlen -= decstate->frame_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
speex_bits_read_from(&decstate->bits, (char *) in, *inlen);
|
||||
*inlen = 0;
|
||||
|
||||
while ( speex_bits_remaining(&decstate->bits) &&
|
||||
*outlen >= decstate->frame_size )
|
||||
{
|
||||
int ret = speex_decode_int(decstate->state, &decstate->bits, out);
|
||||
|
||||
// from speex/speex.h, speex_decode returns:
|
||||
// @return return status (0 for no error, -1 for end of stream, -2 other)
|
||||
if (ret == 0)
|
||||
{
|
||||
/* one frame of output */
|
||||
*outlen -= decstate->frame_size;
|
||||
out += decstate->frame_size;
|
||||
} else if (ret == -1)
|
||||
{
|
||||
/* at end of stream, or just a terminator */
|
||||
int bits_left = speex_bits_remaining(&decstate->bits) % 8;
|
||||
if(bits_left >= 5)
|
||||
speex_bits_advance(&decstate->bits, bits_left);
|
||||
else
|
||||
break;
|
||||
} else
|
||||
{
|
||||
/* maybe there's not a whole frame somehow? */
|
||||
fprintf(stderr, "decode_int returned non-zero => %d\n",ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encode( struct iaxc_audio_codec *c,
|
||||
int *inlen, short *in, int *outlen, unsigned char *out )
|
||||
{
|
||||
int bytes;
|
||||
struct State * encstate = (struct State *) c->encstate;
|
||||
|
||||
/* need to encode minimum of encstate->frame_size samples */
|
||||
|
||||
/* only add terminator at end of bits */
|
||||
speex_bits_reset(&encstate->bits);
|
||||
|
||||
/* need to encode minimum of encstate->frame_size samples */
|
||||
while(*inlen >= encstate->frame_size)
|
||||
{
|
||||
//fprintf(stderr, "encode: inlen=%d outlen=%d\n", *inlen, *outlen);
|
||||
speex_encode_int(encstate->state, in, &encstate->bits);
|
||||
*inlen -= encstate->frame_size;
|
||||
in += encstate->frame_size;
|
||||
}
|
||||
|
||||
/* add terminator */
|
||||
speex_bits_pack(&encstate->bits, 15, 5);
|
||||
|
||||
bytes = speex_bits_write(&encstate->bits, (char *) out, *outlen);
|
||||
|
||||
/* can an error happen here? no bytes? */
|
||||
*outlen -= bytes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_speex_new(struct iaxc_speex_settings *set)
|
||||
{
|
||||
struct State * encstate;
|
||||
struct State * decstate;
|
||||
struct iaxc_audio_codec *c = (struct iaxc_audio_codec *)calloc(sizeof(struct iaxc_audio_codec),1);
|
||||
const SpeexMode *sm;
|
||||
|
||||
if(!c)
|
||||
return c;
|
||||
|
||||
strcpy(c->name,"speex");
|
||||
c->format = IAXC_FORMAT_SPEEX;
|
||||
c->encode = encode;
|
||||
c->decode = decode;
|
||||
c->destroy = destroy;
|
||||
|
||||
c->encstate = calloc(sizeof(struct State),1);
|
||||
c->decstate = calloc(sizeof(struct State),1);
|
||||
|
||||
/* leaks a bit on no-memory */
|
||||
if(!(c->encstate && c->decstate))
|
||||
return NULL;
|
||||
|
||||
encstate = (struct State *) c->encstate;
|
||||
decstate = (struct State *) c->decstate;
|
||||
|
||||
sm = speex_lib_get_mode(SPEEX_MODEID_NB);
|
||||
|
||||
encstate->state = speex_encoder_init(sm);
|
||||
decstate->state = speex_decoder_init(sm);
|
||||
speex_bits_init(&encstate->bits);
|
||||
speex_bits_init(&decstate->bits);
|
||||
speex_bits_reset(&encstate->bits);
|
||||
speex_bits_reset(&decstate->bits);
|
||||
|
||||
speex_decoder_ctl(decstate->state, SPEEX_SET_ENH, &set->decode_enhance);
|
||||
|
||||
speex_encoder_ctl(encstate->state, SPEEX_SET_COMPLEXITY, &set->complexity);
|
||||
|
||||
if(set->quality >= 0) {
|
||||
if(set->vbr) {
|
||||
speex_encoder_ctl(encstate->state, SPEEX_SET_VBR_QUALITY, &set->quality);
|
||||
} else {
|
||||
int quality = (int)set->quality;
|
||||
speex_encoder_ctl(encstate->state, SPEEX_SET_QUALITY, &quality);
|
||||
}
|
||||
}
|
||||
if(set->bitrate >= 0)
|
||||
speex_encoder_ctl(encstate->state, SPEEX_SET_BITRATE, &set->bitrate);
|
||||
if(set->vbr)
|
||||
speex_encoder_ctl(encstate->state, SPEEX_SET_VBR, &set->vbr);
|
||||
if(set->abr)
|
||||
speex_encoder_ctl(encstate->state, SPEEX_SET_ABR, &set->abr);
|
||||
|
||||
/* set up frame sizes (normally, this is 20ms worth) */
|
||||
speex_encoder_ctl(encstate->state,SPEEX_GET_FRAME_SIZE,&encstate->frame_size);
|
||||
speex_decoder_ctl(decstate->state,SPEEX_GET_FRAME_SIZE,&decstate->frame_size);
|
||||
|
||||
c->minimum_frame_size = 160;
|
||||
|
||||
if(encstate->frame_size > c->minimum_frame_size)
|
||||
c->minimum_frame_size = encstate->frame_size;
|
||||
if(decstate->frame_size > c->minimum_frame_size)
|
||||
c->minimum_frame_size = decstate->frame_size;
|
||||
|
||||
if(!(encstate->state && decstate->state))
|
||||
return NULL;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#include "speex/speex.h"
|
||||
|
||||
struct iaxc_speex_settings {
|
||||
int decode_enhance;
|
||||
float quality;
|
||||
int bitrate;
|
||||
int vbr;
|
||||
int abr; /* abr bitrate */
|
||||
int complexity;
|
||||
};
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_speex_new(struct iaxc_speex_settings *settings);
|
||||
+502
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
* Mihai Balea <mihai at hates dot ms>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some comments about Theora streaming
|
||||
* Theora video codec has two problems when it comes to streaming
|
||||
* and broadcasting video:
|
||||
*
|
||||
* - Large headers that need to be passed from the encoder to the decoder
|
||||
* to initialize it. The conventional wisdom says we should transfer the
|
||||
* headers out of band, but that complicates things with IAX, which does
|
||||
* not have a separate signalling channel. Also, it makes things really
|
||||
* difficult in a video conference scenario, where video gets switched
|
||||
* between participants regularly. To solve this issue, we initialize
|
||||
* the encoder and the decoder at the same time, using the headers from
|
||||
* the local encoder to initialize the decoder. This works if the
|
||||
* endpoints use the exact same version of Theora and the exact same
|
||||
* parameters for initialization.
|
||||
*
|
||||
* - No support for splitting the frame into multiple slices. Frames can
|
||||
* be relatively large. For a 320x240 video stream, you can see key
|
||||
* frames larger than 9KB, which is the maximum UDP packet size on Mac
|
||||
* OS X. To work around this limitation, we use the slice API to fragment
|
||||
* encoded frames to a reasonable size that UDP can safely transport
|
||||
*
|
||||
* Other miscellaneous comments:
|
||||
*
|
||||
* - For quality reasons, when we detect a video stream switch, we reject all
|
||||
* incoming frames until we receive a key frame.
|
||||
*
|
||||
* - Theora only accepts video that has dimensions multiple of 16. If we combine
|
||||
* his with a 4:3 aspect ratio requirement, we get a very limited number
|
||||
* of available resolutions. To work around this limitation, we pad the video
|
||||
* on encoding, up to the closest multiple of 16. On the decoding side, we
|
||||
* remove the padding. This way, video resolution can be any multiple of 2
|
||||
*
|
||||
* We should probably look more into this (how to deal with missing and
|
||||
* out of order slices)
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "iaxclient_lib.h"
|
||||
#include "video.h"
|
||||
#include "slice.h"
|
||||
#include "codec_theora.h"
|
||||
#include <theora/theora.h>
|
||||
|
||||
#define MAX_SLICE_SIZE 8000
|
||||
|
||||
struct theora_decoder
|
||||
{
|
||||
theora_state td;
|
||||
theora_info ti;
|
||||
theora_comment tc;
|
||||
struct deslicer_context *dsc;
|
||||
int got_key_frame;
|
||||
};
|
||||
|
||||
struct theora_encoder
|
||||
{
|
||||
theora_state td;
|
||||
theora_info ti;
|
||||
theora_comment tc;
|
||||
int needs_padding;
|
||||
struct slicer_context *sc;
|
||||
unsigned char *pad_buffer;
|
||||
};
|
||||
|
||||
static void destroy( struct iaxc_video_codec *c)
|
||||
{
|
||||
struct theora_encoder *e;
|
||||
struct theora_decoder *d;
|
||||
|
||||
if ( !c )
|
||||
return;
|
||||
|
||||
if ( c->encstate )
|
||||
{
|
||||
e = (struct theora_encoder *)c->encstate;
|
||||
if ( e->pad_buffer )
|
||||
free(e->pad_buffer);
|
||||
if ( e->sc )
|
||||
free_slicer_context(e->sc);
|
||||
theora_comment_clear(&e->tc);
|
||||
theora_info_clear(&e->ti);
|
||||
theora_clear(&e->td);
|
||||
free(e);
|
||||
}
|
||||
if ( c->decstate )
|
||||
{
|
||||
d = (struct theora_decoder *)c->decstate;
|
||||
if ( d->dsc )
|
||||
free_deslicer_context(d->dsc);
|
||||
theora_comment_clear(&d->tc);
|
||||
theora_info_clear(&d->ti);
|
||||
theora_clear(&d->td);
|
||||
free(c->decstate);
|
||||
}
|
||||
free(c);
|
||||
}
|
||||
|
||||
static int decode(struct iaxc_video_codec *c, int inlen, const char *in,
|
||||
int *outlen, char *out)
|
||||
{
|
||||
struct theora_decoder *d;
|
||||
ogg_packet op;
|
||||
yuv_buffer picture;
|
||||
unsigned int line;
|
||||
int my_out_len;
|
||||
int w, h, ph;
|
||||
int flen;
|
||||
char *frame;
|
||||
|
||||
// Sanity checks
|
||||
if ( !c || !c->decstate || !in || inlen <= 0 || !out || !outlen )
|
||||
return -1;
|
||||
|
||||
// Assemble slices
|
||||
d = (struct theora_decoder *)c->decstate;
|
||||
if ( !d->dsc )
|
||||
return -1;
|
||||
|
||||
frame = deslice(in, inlen, &flen, d->dsc);
|
||||
if ( frame == NULL )
|
||||
return 1;
|
||||
|
||||
/* decode into an OP structure */
|
||||
memset(&op, 0, sizeof(op));
|
||||
op.bytes = flen;
|
||||
op.packet = (unsigned char *)frame;
|
||||
|
||||
/* reject all incoming frames until we get a key frame */
|
||||
if ( !d->got_key_frame )
|
||||
{
|
||||
if ( theora_packet_iskeyframe(&op) )
|
||||
d->got_key_frame = 1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( theora_decode_packetin(&d->td, &op) == OC_BADPACKET )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"codec_theora: warning: theora_decode_packetin says bad packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
w = d->ti.frame_width;
|
||||
h = d->ti.frame_height;
|
||||
ph = d->ti.height;
|
||||
|
||||
my_out_len = d->ti.frame_width * d->ti.frame_height * 3 / 2;
|
||||
|
||||
/* make sure we have enough room for the goodies */
|
||||
if ( *outlen < my_out_len )
|
||||
{
|
||||
fprintf(stderr, "codec_theora: not enough room for decoding\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* finally, here's where we get our goodies */
|
||||
if ( theora_decode_YUVout(&d->td, &picture) )
|
||||
{
|
||||
fprintf(stderr, "codec_theora: error getting our goodies\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//clear output
|
||||
memset(out, 127, my_out_len);
|
||||
|
||||
for( line = 0 ; line < d->ti.frame_height / 2 ; line++ )
|
||||
{
|
||||
// Y-even
|
||||
memcpy(out + picture.y_width * 2 * line,
|
||||
picture.y + 2 * line * picture.y_stride,
|
||||
picture.y_width);
|
||||
// Y-odd
|
||||
memcpy(out + picture.y_width * (2 * line + 1),
|
||||
picture.y + (2 * line + 1) * picture.y_stride,
|
||||
picture.y_width);
|
||||
// U + V
|
||||
memcpy(out + (d->ti.frame_width * d->ti.frame_height) + line * d->ti.frame_width / 2,
|
||||
picture.u + line * picture.uv_stride,
|
||||
picture.uv_width);
|
||||
memcpy(out + (d->ti.frame_width * d->ti.frame_height * 5 / 4) + line * d->ti.frame_width / 2,
|
||||
picture.v + line * picture.uv_stride,
|
||||
picture.uv_width);
|
||||
}
|
||||
|
||||
*outlen = my_out_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Pads a w by h frame to bring it up to pw by ph size using value
|
||||
static void pad_channel(const char *src, int w, int h, unsigned char *dst,
|
||||
int pw, int ph, unsigned char value)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( w == pw )
|
||||
{
|
||||
// We don't need to pad each line, just copy the data
|
||||
memcpy(dst, src, w * h);
|
||||
} else
|
||||
{
|
||||
// We DO need to pad each line
|
||||
for ( i=0 ; i<h ; i++ )
|
||||
{
|
||||
memcpy(&dst[i*pw], &src[i*w], w);
|
||||
memset(&dst[i*pw+w], value, pw-w);
|
||||
}
|
||||
}
|
||||
// Pad the bottom of the frame if necessary
|
||||
if ( h < ph )
|
||||
memset(dst + pw * h, value, (ph - h) * pw);
|
||||
}
|
||||
|
||||
static int encode(struct iaxc_video_codec * c, int inlen, const char * in,
|
||||
struct slice_set_t * slice_set)
|
||||
{
|
||||
struct theora_encoder *e;
|
||||
ogg_packet op;
|
||||
yuv_buffer picture;
|
||||
|
||||
// Sanity checks
|
||||
if ( !c || !c->encstate || !in || !slice_set )
|
||||
return -1;
|
||||
|
||||
e = (struct theora_encoder *)c->encstate;
|
||||
|
||||
// Prepare the YUV buffer
|
||||
if ( e->needs_padding )
|
||||
{
|
||||
// We copy a padded image into the pad buffer and set up the pointers
|
||||
// Use pad_channel for each of the YUV channels
|
||||
// Use a pad value of 0 for luma and 128 for chroma
|
||||
pad_channel(in,
|
||||
e->ti.frame_width,
|
||||
e->ti.frame_height,
|
||||
e->pad_buffer,
|
||||
e->ti.width,
|
||||
e->ti.height,
|
||||
0);
|
||||
|
||||
pad_channel(in + e->ti.frame_width * e->ti.frame_height,
|
||||
e->ti.frame_width / 2,
|
||||
e->ti.frame_height / 2,
|
||||
e->pad_buffer + e->ti.width * e->ti.height,
|
||||
e->ti.width / 2,
|
||||
e->ti.height / 2,
|
||||
128);
|
||||
|
||||
pad_channel(in + e->ti.frame_width * e->ti.frame_height * 5 / 4,
|
||||
e->ti.frame_width / 2,
|
||||
e->ti.frame_height / 2,
|
||||
e->pad_buffer + e->ti.width * e->ti.height * 5 / 4,
|
||||
e->ti.width / 2,
|
||||
e->ti.height / 2,
|
||||
128);
|
||||
|
||||
picture.y = e->pad_buffer;
|
||||
} else
|
||||
{
|
||||
// use the original buffer
|
||||
picture.y = (unsigned char *)in;
|
||||
}
|
||||
picture.u = picture.y + e->ti.width * e->ti.height;
|
||||
picture.v = picture.u + e->ti.width * e->ti.height / 4;
|
||||
picture.y_width = e->ti.width;
|
||||
picture.y_height = e->ti.height;
|
||||
picture.y_stride = e->ti.width;
|
||||
picture.uv_width = e->ti.width / 2;
|
||||
picture.uv_height = e->ti.height / 2;
|
||||
picture.uv_stride = e->ti.width / 2;
|
||||
|
||||
// Send data in for encoding
|
||||
if ( theora_encode_YUVin(&e->td, &picture) )
|
||||
{
|
||||
fprintf(stderr, "codec_theora: failed theora_encode_YUVin\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get data from the encoder
|
||||
if ( theora_encode_packetout(&e->td, 0, &op) != 1 )
|
||||
{
|
||||
fprintf(stderr, "codec_theora: failed theora_encode_packetout\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check to see if we have a key frame
|
||||
slice_set->key_frame = theora_packet_iskeyframe(&op) == 1;
|
||||
|
||||
// Slice the frame
|
||||
slice((char *)op.packet, op.bytes, slice_set, e->sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iaxc_video_codec *codec_video_theora_new(int format, int w, int h,
|
||||
int framerate, int bitrate, int fragsize)
|
||||
{
|
||||
struct iaxc_video_codec *c;
|
||||
struct theora_encoder *e;
|
||||
struct theora_decoder *d;
|
||||
unsigned short source_id;
|
||||
ogg_packet headerp, commentp, tablep;
|
||||
|
||||
/* Basic sanity checks */
|
||||
if ( w <= 0 || h <= 0 || framerate <= 0 || bitrate <= 0 || fragsize <= 0 )
|
||||
{
|
||||
fprintf(stderr, "codec_theora: bogus codec params: %d %d %d %d %d\n",
|
||||
w, h, framerate, bitrate, fragsize);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( w % 2 || h % 2 )
|
||||
{
|
||||
fprintf(stderr, "codec_theora: video dimensions must be multiples of 2\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( fragsize > MAX_SLICE_SIZE )
|
||||
fragsize = MAX_SLICE_SIZE;
|
||||
|
||||
c = (struct iaxc_video_codec *)calloc(sizeof(struct iaxc_video_codec), 1);
|
||||
|
||||
if ( !c )
|
||||
goto bail;
|
||||
|
||||
c->decstate = calloc(sizeof(struct theora_decoder), 1);
|
||||
|
||||
if ( !c->decstate )
|
||||
goto bail;
|
||||
|
||||
c->encstate = calloc(sizeof(struct theora_encoder), 1);
|
||||
|
||||
if ( !c->encstate )
|
||||
goto bail;
|
||||
|
||||
c->format = format;
|
||||
c->width = w;
|
||||
c->height = h;
|
||||
c->framerate = framerate;
|
||||
c->bitrate = bitrate;
|
||||
c->fragsize = fragsize;
|
||||
|
||||
c->encode = encode;
|
||||
c->decode = decode;
|
||||
c->destroy = destroy;
|
||||
|
||||
e = (struct theora_encoder *)c->encstate;
|
||||
d = (struct theora_decoder *)c->decstate;
|
||||
|
||||
// Initialize slicer
|
||||
// Generate random source id
|
||||
srand((unsigned int)time(0));
|
||||
source_id = rand() & 0xffff;
|
||||
e->sc = create_slicer_context(source_id, fragsize);
|
||||
if ( !e->sc )
|
||||
goto bail;
|
||||
|
||||
|
||||
/* set up some parameters in the contexts */
|
||||
|
||||
theora_info_init(&e->ti);
|
||||
|
||||
/* set up common parameters */
|
||||
e->ti.frame_width = w;
|
||||
e->ti.frame_height = h;
|
||||
e->ti.width = ((w - 1) / 16 + 1) * 16;
|
||||
e->ti.height = ((h - 1) / 16 + 1) * 16;
|
||||
e->ti.offset_x = 0;
|
||||
e->ti.offset_y = 0;
|
||||
|
||||
// We set up a padded frame with dimensions that are multiple of 16
|
||||
// We allocate a buffer to hold this frame
|
||||
e->needs_padding = e->ti.width != e->ti.frame_width ||
|
||||
e->ti.height != e->ti.frame_height;
|
||||
|
||||
if ( e->needs_padding )
|
||||
{
|
||||
e->pad_buffer = (unsigned char *)
|
||||
malloc(e->ti.width * e->ti.height * 3 / 2);
|
||||
|
||||
if ( !e->pad_buffer )
|
||||
goto bail;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->pad_buffer = 0;
|
||||
}
|
||||
|
||||
e->ti.fps_numerator = framerate;
|
||||
e->ti.fps_denominator = 1;
|
||||
|
||||
e->ti.aspect_numerator = 1;
|
||||
e->ti.aspect_denominator = 1;
|
||||
|
||||
e->ti.colorspace = OC_CS_UNSPECIFIED;
|
||||
e->ti.pixelformat = OC_PF_420;
|
||||
|
||||
e->ti.target_bitrate = bitrate;
|
||||
|
||||
e->ti.quality = 0;
|
||||
|
||||
e->ti.dropframes_p = 0;
|
||||
e->ti.quick_p = 1;
|
||||
e->ti.keyframe_auto_p = 0;
|
||||
e->ti.keyframe_frequency = framerate;
|
||||
e->ti.keyframe_frequency_force = framerate;
|
||||
e->ti.keyframe_data_target_bitrate = bitrate * 3;
|
||||
e->ti.keyframe_auto_threshold = 80;
|
||||
e->ti.keyframe_mindistance = 8;
|
||||
e->ti.noise_sensitivity = 0;
|
||||
|
||||
if ( theora_encode_init(&e->td, &e->ti) )
|
||||
goto bail;
|
||||
|
||||
// Obtain the encoder headers and set up the decoder headers from
|
||||
// data in the encoder headers
|
||||
memset(&headerp, 0, sizeof(headerp));
|
||||
memset(&commentp, 0, sizeof(commentp));
|
||||
memset(&tablep, 0, sizeof(tablep));
|
||||
|
||||
// Set up the decoder using the encoder headers
|
||||
theora_info_init(&d->ti);
|
||||
theora_comment_init(&d->tc);
|
||||
theora_comment_init(&e->tc);
|
||||
|
||||
if ( theora_encode_header(&e->td, &headerp) )
|
||||
goto bail;
|
||||
|
||||
headerp.b_o_s = 1;
|
||||
|
||||
if ( theora_decode_header(&d->ti, &d->tc, &headerp) )
|
||||
goto bail;
|
||||
|
||||
if ( theora_encode_comment(&e->tc, &commentp) )
|
||||
goto bail;
|
||||
|
||||
if ( theora_decode_header(&d->ti, &d->tc, &commentp) )
|
||||
goto bail;
|
||||
|
||||
theora_comment_clear(&e->tc);
|
||||
|
||||
if ( theora_encode_tables(&e->td, &tablep) )
|
||||
goto bail;
|
||||
|
||||
if ( theora_decode_header(&d->ti, &d->tc, &tablep) )
|
||||
goto bail;
|
||||
|
||||
if ( theora_decode_init(&d->td, &d->ti) )
|
||||
goto bail;
|
||||
|
||||
d->got_key_frame = 0;
|
||||
|
||||
// Initialize deslicer context
|
||||
d->dsc = create_deslicer_context(c->fragsize);
|
||||
if ( !d->dsc )
|
||||
goto bail;
|
||||
|
||||
strcpy(c->name, "Theora");
|
||||
return c;
|
||||
|
||||
bail:
|
||||
fprintf(stderr, "codec_theora: failed to initialize encoder or decoder\n");
|
||||
|
||||
if ( c )
|
||||
{
|
||||
if ( c->encstate )
|
||||
{
|
||||
e = (struct theora_encoder *)c->encstate;
|
||||
if ( e->sc )
|
||||
free_slicer_context(e->sc);
|
||||
free(c->encstate);
|
||||
}
|
||||
if ( c->decstate )
|
||||
{
|
||||
d = (struct theora_decoder *)c->decstate;
|
||||
if ( d->dsc )
|
||||
free_deslicer_context(d->dsc);
|
||||
free(c->decstate);
|
||||
}
|
||||
free(c);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
* Mihai Balea <mihai at hates dot ms>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
struct iaxc_video_codec *codec_video_theora_new(int format, int w, int h,
|
||||
int framerate, int bitrate, int fragsize);
|
||||
Vendored
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
#include "codec_ulaw.h"
|
||||
#include "iaxclient_lib.h"
|
||||
|
||||
struct state {
|
||||
plc_state_t plc;
|
||||
};
|
||||
|
||||
static short ulaw_2lin [256];
|
||||
static unsigned char lin_2ulaw [16384];
|
||||
static int initialized=0;
|
||||
|
||||
/* this looks similar to asterisk, but comes from public domain code by craig reese
|
||||
I've just followed asterisk's table sizes for lin_2u, and also too lazy to do binary arith to decide which
|
||||
iterations to skip -- this way we get the same result.. */
|
||||
static void initialize() {
|
||||
int i;
|
||||
|
||||
/* ulaw_2lin */
|
||||
for(i=0;i<256;i++) {
|
||||
int b = ~i;
|
||||
int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764};
|
||||
int sign, exponent, mantissa, sample;
|
||||
|
||||
sign = (b & 0x80);
|
||||
exponent = (b >> 4) & 0x07;
|
||||
mantissa = b & 0x0F;
|
||||
sample = exp_lut[exponent] + (mantissa << (exponent + 3));
|
||||
if (sign != 0) sample = -sample;
|
||||
ulaw_2lin[i] = sample;
|
||||
}
|
||||
|
||||
/* lin_2ulaw */
|
||||
for(i=-32767;i<32768;i+=4) {
|
||||
int sample = i;
|
||||
int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
|
||||
int sign, exponent, mantissa;
|
||||
unsigned char ulawbyte;
|
||||
|
||||
/* Get the sample into sign-magnitude. */
|
||||
sign = (sample >> 8) & 0x80; /* set aside the sign */
|
||||
if (sign != 0) sample = -sample; /* get magnitude */
|
||||
if (sample > 32635) sample = 32635; /* clip the magnitude */
|
||||
|
||||
/* Convert from 16 bit linear to ulaw. */
|
||||
sample = sample + 0x84;
|
||||
exponent = exp_lut[(sample >> 7) & 0xFF];
|
||||
mantissa = (sample >> (exponent + 3)) & 0x0F;
|
||||
ulawbyte = ~(sign | (exponent << 4) | mantissa);
|
||||
if (ulawbyte == 0) ulawbyte = 0x02; /* optional CCITT trap */
|
||||
|
||||
lin_2ulaw[((unsigned short)i) >> 2] = ulawbyte;
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
static void destroy ( struct iaxc_audio_codec *c) {
|
||||
if ( c->decstate )
|
||||
free(c->decstate);
|
||||
free(c);
|
||||
}
|
||||
|
||||
|
||||
static int decode ( struct iaxc_audio_codec *c,
|
||||
int *inlen, unsigned char *in, int *outlen, short *out ) {
|
||||
struct state *state = (struct state *)c->decstate;
|
||||
short *orig_out = out;
|
||||
short sample;
|
||||
|
||||
if(*inlen == 0) {
|
||||
int interp_len = 160;
|
||||
if(*outlen < interp_len) interp_len = *outlen;
|
||||
plc_fillin(&state->plc,out,interp_len);
|
||||
*outlen -= interp_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((*inlen > 0) && (*outlen > 0)) {
|
||||
sample = ulaw_2lin[(unsigned char)*(in++)];
|
||||
*(out++) = sample;
|
||||
(*inlen)--; (*outlen)--;
|
||||
}
|
||||
plc_rx(&state->plc, orig_out, (int)(out - orig_out));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encode ( struct iaxc_audio_codec *c,
|
||||
int *inlen, short *in, int *outlen, unsigned char *out ) {
|
||||
|
||||
while ((*inlen > 0) && (*outlen > 0)) {
|
||||
*(out++) = lin_2ulaw[((unsigned short)*(in++)) >> 2];
|
||||
(*inlen)--; (*outlen)--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_ulaw_new() {
|
||||
|
||||
struct iaxc_audio_codec *c = (struct iaxc_audio_codec *)calloc(sizeof(struct iaxc_audio_codec),1);
|
||||
|
||||
if(!c) return c;
|
||||
|
||||
if(!initialized) initialize();
|
||||
|
||||
strcpy(c->name,"ulaw");
|
||||
c->format = IAXC_FORMAT_ULAW;
|
||||
c->encode = encode;
|
||||
c->decode = decode;
|
||||
c->destroy = destroy;
|
||||
|
||||
/* really, we can use less, but don't want to */
|
||||
c->minimum_frame_size = 160;
|
||||
|
||||
/* decoder state, used for interpolation */
|
||||
c->decstate = calloc(sizeof(struct state),1);
|
||||
plc_init(&((struct state *)c->decstate)->plc);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
|
||||
struct iaxc_audio_codec *codec_audio_ulaw_new();
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
Technische Universitaet Berlin
|
||||
|
||||
Any use of this software is permitted provided that this notice is not
|
||||
removed and that neither the authors nor the Technische Universitaet Berlin
|
||||
are deemed to have made any representations as to the suitability of this
|
||||
software for any purpose nor are held responsible for any defects of
|
||||
this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
|
||||
As a matter of courtesy, the authors request to be informed about uses
|
||||
this software has found, about bugs in this software, and about any
|
||||
improvements that may be of general interest.
|
||||
|
||||
Berlin, 28.11.1994
|
||||
Jutta Degener
|
||||
Carsten Bormann
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*$Header$*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
/*efine SIGHANDLER_T int / * signal handlers are void */
|
||||
/*efine HAS_SYSV_SIGNAL 1 / * sigs not blocked/reset? */
|
||||
|
||||
#define HAS_STDLIB_H 1 /* /usr/include/stdlib.h */
|
||||
/*efine HAS_LIMITS_H 1 / * /usr/include/limits.h */
|
||||
#define HAS_FCNTL_H 1 /* /usr/include/fcntl.h */
|
||||
/*efine HAS_ERRNO_DECL 1 / * errno.h declares errno */
|
||||
|
||||
#define HAS_FSTAT 1 /* fstat syscall */
|
||||
#define HAS_FCHMOD 1 /* fchmod syscall */
|
||||
#define HAS_CHMOD 1 /* chmod syscall */
|
||||
#define HAS_FCHOWN 1 /* fchown syscall */
|
||||
#define HAS_CHOWN 1 /* chown syscall */
|
||||
/*efine HAS__FSETMODE 1 / * _fsetmode -- set file mode */
|
||||
|
||||
#define HAS_STRING_H 1 /* /usr/include/string.h */
|
||||
/*efine HAS_STRINGS_H 1 / * /usr/include/strings.h */
|
||||
|
||||
#define HAS_UNISTD_H 1 /* /usr/include/unistd.h */
|
||||
#define HAS_UTIME 1 /* POSIX utime(path, times) */
|
||||
/*efine HAS_UTIMES 1 / * use utimes() syscall instead */
|
||||
#define HAS_UTIME_H 1 /* UTIME header file */
|
||||
/*efine HAS_UTIMBUF 1 / * struct utimbuf */
|
||||
/*efine HAS_UTIMEUSEC 1 / * microseconds in utimbuf? */
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
Vendored
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*$Header$*/
|
||||
|
||||
#ifndef GSM_H
|
||||
#define GSM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define NeedFunctionPrototypes 1
|
||||
#endif
|
||||
|
||||
#if __STDC__
|
||||
# define NeedFunctionPrototypes 1
|
||||
#endif
|
||||
|
||||
#ifdef _NO_PROTO
|
||||
# undef NeedFunctionPrototypes
|
||||
#endif
|
||||
|
||||
#ifdef NeedFunctionPrototypes
|
||||
# include <stdio.h> /* for FILE * */
|
||||
#endif
|
||||
|
||||
#undef GSM_P
|
||||
#if NeedFunctionPrototypes
|
||||
# define GSM_P( protos ) protos
|
||||
#else
|
||||
# define GSM_P( protos ) ( /* protos */ )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interface
|
||||
*/
|
||||
|
||||
typedef struct gsm_state * gsm;
|
||||
typedef short gsm_signal; /* signed 16 bit */
|
||||
typedef unsigned char gsm_byte;
|
||||
typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */
|
||||
|
||||
#define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */
|
||||
|
||||
#define GSM_PATCHLEVEL 10
|
||||
#define GSM_MINOR 0
|
||||
#define GSM_MAJOR 1
|
||||
|
||||
#define GSM_OPT_VERBOSE 1
|
||||
#define GSM_OPT_FAST 2
|
||||
#define GSM_OPT_LTP_CUT 3
|
||||
#define GSM_OPT_WAV49 4
|
||||
#define GSM_OPT_FRAME_INDEX 5
|
||||
#define GSM_OPT_FRAME_CHAIN 6
|
||||
|
||||
extern gsm gsm_create GSM_P((void));
|
||||
extern void gsm_destroy GSM_P((gsm));
|
||||
|
||||
extern int gsm_print GSM_P((FILE *, gsm, gsm_byte *));
|
||||
extern int gsm_option GSM_P((gsm, int, int *));
|
||||
|
||||
extern void gsm_encode GSM_P((gsm, gsm_signal *, gsm_byte *));
|
||||
extern int gsm_decode GSM_P((gsm, gsm_byte *, gsm_signal *));
|
||||
|
||||
extern int gsm_explode GSM_P((gsm, gsm_byte *, gsm_signal *));
|
||||
extern void gsm_implode GSM_P((gsm, gsm_signal *, gsm_byte *));
|
||||
|
||||
#undef GSM_P
|
||||
|
||||
#endif /* GSM_H */
|
||||
+308
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*$Header$*/
|
||||
|
||||
#ifndef PRIVATE_H
|
||||
#define PRIVATE_H
|
||||
|
||||
typedef short word; /* 16 bit signed int */
|
||||
typedef long longword; /* 32 bit signed int */
|
||||
|
||||
typedef unsigned short uword; /* unsigned word */
|
||||
typedef unsigned long ulongword; /* unsigned longword */
|
||||
|
||||
struct gsm_state {
|
||||
|
||||
word dp0[ 280 ];
|
||||
|
||||
word z1; /* preprocessing.c, Offset_com. */
|
||||
longword L_z2; /* Offset_com. */
|
||||
int mp; /* Preemphasis */
|
||||
|
||||
word u[8]; /* short_term_aly_filter.c */
|
||||
word LARpp[2][8]; /* */
|
||||
word j; /* */
|
||||
|
||||
word ltp_cut; /* long_term.c, LTP crosscorr. */
|
||||
word nrp; /* 40 */ /* long_term.c, synthesis */
|
||||
word v[9]; /* short_term.c, synthesis */
|
||||
word msr; /* decoder.c, Postprocessing */
|
||||
|
||||
char verbose; /* only used if !NDEBUG */
|
||||
char fast; /* only used if FAST */
|
||||
|
||||
char wav_fmt; /* only used if WAV49 defined */
|
||||
unsigned char frame_index; /* odd/even chaining */
|
||||
unsigned char frame_chain; /* half-byte to carry forward */
|
||||
};
|
||||
|
||||
|
||||
#define MIN_WORD (-32767 - 1)
|
||||
#define MAX_WORD 32767
|
||||
|
||||
#define MIN_LONGWORD (-2147483647 - 1)
|
||||
#define MAX_LONGWORD 2147483647
|
||||
|
||||
#ifdef SASR /* flag: >> is a signed arithmetic shift right */
|
||||
#undef SASR
|
||||
#define SASR(x, by) ((x) >> (by))
|
||||
#else
|
||||
#define SASR(x, by) ((x) >= 0 ? (x) >> (by) : (~(-((x) + 1) >> (by))))
|
||||
#endif /* SASR */
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
/*
|
||||
* Prototypes from add.c
|
||||
*/
|
||||
extern word gsm_mult P((word a, word b));
|
||||
extern longword gsm_L_mult P((word a, word b));
|
||||
extern word gsm_mult_r P((word a, word b));
|
||||
|
||||
extern word gsm_div P((word num, word denum));
|
||||
|
||||
extern word gsm_add P(( word a, word b ));
|
||||
extern longword gsm_L_add P(( longword a, longword b ));
|
||||
|
||||
extern word gsm_sub P((word a, word b));
|
||||
extern longword gsm_L_sub P((longword a, longword b));
|
||||
|
||||
extern word gsm_abs P((word a));
|
||||
|
||||
extern word gsm_norm P(( longword a ));
|
||||
|
||||
extern longword gsm_L_asl P((longword a, int n));
|
||||
extern word gsm_asl P((word a, int n));
|
||||
|
||||
extern longword gsm_L_asr P((longword a, int n));
|
||||
extern word gsm_asr P((word a, int n));
|
||||
|
||||
/*
|
||||
* Inlined functions from add.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* #define GSM_MULT_R(a, b) (* word a, word b, !(a == b == MIN_WORD) *) \
|
||||
* (0x0FFFF & SASR(((longword)(a) * (longword)(b) + 16384), 15))
|
||||
*/
|
||||
#define GSM_MULT_R(a, b) /* word a, word b, !(a == b == MIN_WORD) */ \
|
||||
(SASR( ((longword)(a) * (longword)(b) + 16384), 15 ))
|
||||
|
||||
# define GSM_MULT(a,b) /* word a, word b, !(a == b == MIN_WORD) */ \
|
||||
(SASR( ((longword)(a) * (longword)(b)), 15 ))
|
||||
|
||||
# define GSM_L_MULT(a, b) /* word a, word b */ \
|
||||
(((longword)(a) * (longword)(b)) << 1)
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
static __inline__ int GSM_L_ADD(int a, int b)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
|
||||
"addl %2,%0; jno 0f; movl $0x7fffffff,%0; adcl $0,%0; 0:"
|
||||
: "=r" (a)
|
||||
: "0" (a), "ir" (b)
|
||||
: "cc"
|
||||
);
|
||||
return(a);
|
||||
}
|
||||
|
||||
static __inline__ short GSM_ADD(short a, short b)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"addw %2,%0; jno 0f; movw $0x7fff,%0; adcw $0,%0; 0:"
|
||||
: "=r" (a)
|
||||
: "0" (a), "ir" (b)
|
||||
: "cc"
|
||||
);
|
||||
return(a);
|
||||
}
|
||||
|
||||
static __inline__ short GSM_SUB(short a, short b)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"subw %2,%0; jno 0f; movw $0x7fff,%0; adcw $0,%0; 0:"
|
||||
: "=r" (a)
|
||||
: "0" (a), "ir" (b)
|
||||
: "cc"
|
||||
);
|
||||
return(a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define GSM_L_ADD(a, b) \
|
||||
( (a) < 0 ? ( (b) >= 0 ? (a) + (b) \
|
||||
: (utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1)) \
|
||||
>= MAX_LONGWORD ? MIN_LONGWORD : -(longword)utmp-2 ) \
|
||||
: ((b) <= 0 ? (a) + (b) \
|
||||
: (utmp = (ulongword)(a) + (ulongword)(b)) >= MAX_LONGWORD \
|
||||
? MAX_LONGWORD : utmp))
|
||||
|
||||
/*
|
||||
* # define GSM_ADD(a, b) \
|
||||
* ((ltmp = (longword)(a) + (longword)(b)) >= MAX_WORD \
|
||||
* ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp)
|
||||
*/
|
||||
/* Nonportable, but faster: */
|
||||
|
||||
#define GSM_ADD(a, b) \
|
||||
(short) ((ulongword)((ltmp = (longword)(a) + (longword)(b)) - MIN_WORD) > \
|
||||
MAX_WORD - MIN_WORD ? (ltmp > 0 ? MAX_WORD : MIN_WORD) : ltmp)
|
||||
|
||||
# define GSM_SUB(a, b) \
|
||||
((ltmp = (longword)(a) - (longword)(b)) >= MAX_WORD \
|
||||
? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp)
|
||||
|
||||
#endif
|
||||
|
||||
# define GSM_ABS(a) ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a))
|
||||
|
||||
/* Use these if necessary:
|
||||
|
||||
# define GSM_MULT_R(a, b) gsm_mult_r(a, b)
|
||||
# define GSM_MULT(a, b) gsm_mult(a, b)
|
||||
# define GSM_L_MULT(a, b) gsm_L_mult(a, b)
|
||||
|
||||
# define GSM_L_ADD(a, b) gsm_L_add(a, b)
|
||||
# define GSM_ADD(a, b) gsm_add(a, b)
|
||||
# define GSM_SUB(a, b) gsm_sub(a, b)
|
||||
|
||||
# define GSM_ABS(a) gsm_abs(a)
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* More prototypes from implementations..
|
||||
*/
|
||||
extern void Gsm_Coder P((
|
||||
struct gsm_state * S,
|
||||
word * s, /* [0..159] samples IN */
|
||||
word * LARc, /* [0..7] LAR coefficients OUT */
|
||||
word * Nc, /* [0..3] LTP lag OUT */
|
||||
word * bc, /* [0..3] coded LTP gain OUT */
|
||||
word * Mc, /* [0..3] RPE grid selection OUT */
|
||||
word * xmaxc,/* [0..3] Coded maximum amplitude OUT */
|
||||
word * xMc /* [13*4] normalized RPE samples OUT */));
|
||||
|
||||
extern void Gsm_Long_Term_Predictor P(( /* 4x for 160 samples */
|
||||
struct gsm_state * S,
|
||||
word * d, /* [0..39] residual signal IN */
|
||||
word * dp, /* [-120..-1] d' IN */
|
||||
word * e, /* [0..40] OUT */
|
||||
word * dpp, /* [0..40] OUT */
|
||||
word * Nc, /* correlation lag OUT */
|
||||
word * bc /* gain factor OUT */));
|
||||
|
||||
extern void Gsm_LPC_Analysis P((
|
||||
struct gsm_state * S,
|
||||
word * s, /* 0..159 signals IN/OUT */
|
||||
word * LARc)); /* 0..7 LARc's OUT */
|
||||
|
||||
extern void Gsm_Preprocess P((
|
||||
struct gsm_state * S,
|
||||
word * s, word * so));
|
||||
|
||||
extern void Gsm_Encoding P((
|
||||
struct gsm_state * S,
|
||||
word * e,
|
||||
word * ep,
|
||||
word * xmaxc,
|
||||
word * Mc,
|
||||
word * xMc));
|
||||
|
||||
extern void Gsm_Short_Term_Analysis_Filter P((
|
||||
struct gsm_state * S,
|
||||
word * LARc, /* coded log area ratio [0..7] IN */
|
||||
word * d /* st res. signal [0..159] IN/OUT */));
|
||||
|
||||
extern void Gsm_Decoder P((
|
||||
struct gsm_state * S,
|
||||
word * LARcr, /* [0..7] IN */
|
||||
word * Ncr, /* [0..3] IN */
|
||||
word * bcr, /* [0..3] IN */
|
||||
word * Mcr, /* [0..3] IN */
|
||||
word * xmaxcr, /* [0..3] IN */
|
||||
word * xMcr, /* [0..13*4] IN */
|
||||
word * s)); /* [0..159] OUT */
|
||||
|
||||
extern void Gsm_Decoding P((
|
||||
struct gsm_state * S,
|
||||
word xmaxcr,
|
||||
word Mcr,
|
||||
word * xMcr, /* [0..12] IN */
|
||||
word * erp)); /* [0..39] OUT */
|
||||
|
||||
extern void Gsm_Long_Term_Synthesis_Filtering P((
|
||||
struct gsm_state* S,
|
||||
word Ncr,
|
||||
word bcr,
|
||||
word * erp, /* [0..39] IN */
|
||||
word * drp)); /* [-120..-1] IN, [0..40] OUT */
|
||||
|
||||
void Gsm_RPE_Decoding P((
|
||||
struct gsm_state *S,
|
||||
word xmaxcr,
|
||||
word Mcr,
|
||||
word * xMcr, /* [0..12], 3 bits IN */
|
||||
word * erp)); /* [0..39] OUT */
|
||||
|
||||
void Gsm_RPE_Encoding P((
|
||||
struct gsm_state * S,
|
||||
word * e, /* -5..-1][0..39][40..44 IN/OUT */
|
||||
word * xmaxc, /* OUT */
|
||||
word * Mc, /* OUT */
|
||||
word * xMc)); /* [0..12] OUT */
|
||||
|
||||
extern void Gsm_Short_Term_Synthesis_Filter P((
|
||||
struct gsm_state * S,
|
||||
word * LARcr, /* log area ratios [0..7] IN */
|
||||
word * drp, /* received d [0...39] IN */
|
||||
word * s)); /* signal s [0..159] OUT */
|
||||
|
||||
extern void Gsm_Update_of_reconstructed_short_time_residual_signal P((
|
||||
word * dpp, /* [0...39] IN */
|
||||
word * ep, /* [0...39] IN */
|
||||
word * dp)); /* [-120...-1] IN/OUT */
|
||||
|
||||
/*
|
||||
* Tables from table.c
|
||||
*/
|
||||
#ifndef GSM_TABLE_C
|
||||
|
||||
extern word gsm_A[8], gsm_B[8], gsm_MIC[8], gsm_MAC[8];
|
||||
extern word gsm_INVA[8];
|
||||
extern word gsm_DLB[4], gsm_QLB[4];
|
||||
extern word gsm_H[11];
|
||||
extern word gsm_NRFAC[8];
|
||||
extern word gsm_FAC[8];
|
||||
|
||||
#endif /* GSM_TABLE_C */
|
||||
|
||||
/*
|
||||
* Debugging
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
|
||||
# define gsm_debug_words(a, b, c, d) /* nil */
|
||||
# define gsm_debug_longwords(a, b, c, d) /* nil */
|
||||
# define gsm_debug_word(a, b) /* nil */
|
||||
# define gsm_debug_longword(a, b) /* nil */
|
||||
|
||||
#else /* !NDEBUG => DEBUG */
|
||||
|
||||
extern void gsm_debug_words P((char * name, int, int, word *));
|
||||
extern void gsm_debug_longwords P((char * name, int, int, longword *));
|
||||
extern void gsm_debug_longword P((char * name, longword));
|
||||
extern void gsm_debug_word P((char * name, word));
|
||||
|
||||
#endif /* !NDEBUG */
|
||||
|
||||
#include "unproto.h"
|
||||
|
||||
#endif /* PRIVATE_H */
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*$Header$*/
|
||||
|
||||
#ifndef PROTO_H
|
||||
#define PROTO_H
|
||||
|
||||
#if __cplusplus
|
||||
# define NeedFunctionPrototypes 1
|
||||
#endif
|
||||
|
||||
#if __STDC__
|
||||
# define NeedFunctionPrototypes 1
|
||||
#endif
|
||||
|
||||
#ifdef _NO_PROTO
|
||||
# undef NeedFunctionPrototypes
|
||||
#endif
|
||||
|
||||
#undef P /* gnu stdio.h actually defines this... */
|
||||
#undef P0
|
||||
#undef P1
|
||||
#undef P2
|
||||
#undef P3
|
||||
#undef P4
|
||||
#undef P5
|
||||
#undef P6
|
||||
#undef P7
|
||||
#undef P8
|
||||
|
||||
#if NeedFunctionPrototypes
|
||||
|
||||
# define P( protos ) protos
|
||||
|
||||
# define P0() (void)
|
||||
# define P1(x, a) (a)
|
||||
# define P2(x, a, b) (a, b)
|
||||
# define P3(x, a, b, c) (a, b, c)
|
||||
# define P4(x, a, b, c, d) (a, b, c, d)
|
||||
# define P5(x, a, b, c, d, e) (a, b, c, d, e)
|
||||
# define P6(x, a, b, c, d, e, f) (a, b, c, d, e, f)
|
||||
# define P7(x, a, b, c, d, e, f, g) (a, b, c, d, e, f, g)
|
||||
# define P8(x, a, b, c, d, e, f, g, h) (a, b, c, d, e, f, g, h)
|
||||
|
||||
#else /* !NeedFunctionPrototypes */
|
||||
|
||||
# define P( protos ) ( /* protos */ )
|
||||
|
||||
# define P0() ()
|
||||
# define P1(x, a) x a;
|
||||
# define P2(x, a, b) x a; b;
|
||||
# define P3(x, a, b, c) x a; b; c;
|
||||
# define P4(x, a, b, c, d) x a; b; c; d;
|
||||
# define P5(x, a, b, c, d, e) x a; b; c; d; e;
|
||||
# define P6(x, a, b, c, d, e, f) x a; b; c; d; e; f;
|
||||
# define P7(x, a, b, c, d, e, f, g) x a; b; c; d; e; f; g;
|
||||
# define P8(x, a, b, c, d, e, f, g, h) x a; b; c; d; e; f; g; h;
|
||||
|
||||
#endif /* !NeedFunctionPrototypes */
|
||||
|
||||
#endif /* PROTO_H */
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*$Header$*/
|
||||
|
||||
#ifdef PROTO_H /* sic */
|
||||
#undef PROTO_H
|
||||
|
||||
#undef P
|
||||
#undef P0
|
||||
#undef P1
|
||||
#undef P2
|
||||
#undef P3
|
||||
#undef P4
|
||||
#undef P5
|
||||
#undef P6
|
||||
#undef P7
|
||||
#undef P8
|
||||
|
||||
#endif /* PROTO_H */
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
; Wedit project file. Syntax: Name = value
|
||||
[libgsm]
|
||||
PrjFiles=18
|
||||
File1=SRC\TABLE.C
|
||||
File2=SRC\SHORT_TERM.C
|
||||
File3=SRC\RPE.C
|
||||
File4=SRC\PREPROCESS.C
|
||||
File5=SRC\LPC.C
|
||||
File6=SRC\LONG_TERM.C
|
||||
File7=SRC\GSM_PRINT.C
|
||||
File8=SRC\GSM_OPTION.C
|
||||
File9=SRC\GSM_IMPLODE.C
|
||||
File10=SRC\GSM_EXPLODE.C
|
||||
File11=SRC\GSM_ENCODE.C
|
||||
File12=SRC\GSM_DESTROY.C
|
||||
File13=SRC\GSM_DECODE.C
|
||||
File14=SRC\GSM_CREATE.C
|
||||
File15=SRC\DECODE.C
|
||||
File16=SRC\DEBUG.C
|
||||
File17=SRC\CODE.C
|
||||
File18=SRC\ADD.C
|
||||
UserCount=1
|
||||
User1=ADMINISTRATOR
|
||||
CmsDirectory=Z:\utils\tools\IAX\DLL\gsm\CMS
|
||||
PutOptions=4
|
||||
GetOptions=0
|
||||
FileOptions=0
|
||||
LockOptions=1
|
||||
UsersOptions=1
|
||||
ProjectFlags=0
|
||||
ExtraCmsFilesCount=0
|
||||
File19=SRC\LPC.C
|
||||
File20=SRC\PREPROCESS.C
|
||||
File21=SRC\RPE.C
|
||||
File22=SRC\SHORT_TERM.C
|
||||
File23=SRC\TABLE.C
|
||||
Frame=0 108 765 642
|
||||
StatusBar=0,0,0,0
|
||||
Name=libgsm
|
||||
CurrentFile=
|
||||
OpenFiles=0
|
||||
ProjectPath=Z:\UTILS\TOOLS\IAX\DLL\GSM
|
||||
SourcesDir=Z:\utils\tools\IAX\DLL\gsm
|
||||
Defines=
|
||||
Includes=c:\programme\lcc\include;z:\utils\tools\iax\dll\gsm\inc
|
||||
Libraries=
|
||||
LinkerArgs=
|
||||
ProjectTime=1218
|
||||
MakeName=c:\programme\lcc\bin\make.exe
|
||||
MakeDir=Z:\utils\tools\IAX\DLL\gsm\lcc
|
||||
Exe=z:\utils\tools\iax\dll\gsm\lcc\libgsm.lib
|
||||
DebuggerArguments=
|
||||
DbgExeName=z:\utils\tools\iax\dll\gsm\lcc\libgsm.lib
|
||||
DbgDir=z:\utils\tools\iax\dll\gsm\lcc
|
||||
CompilerFlags=1032
|
||||
FortranFlags=0
|
||||
EiffelFlags=0
|
||||
Useframework=0
|
||||
NumberOfBreakpoints=0
|
||||
ErrorFile=
|
||||
NrOfFileProcessors=0
|
||||
UserName=ADMINISTRATOR
|
||||
OpenFile1="z:\utils\tools\iax\dll\gsm\src\table.c" 18 146 204 820 391
|
||||
OpenFile2="c:\test\ax\gsm\src\code.c" 12 181 233 877 610
|
||||
File24=C:\PROGRAMME\LCC\LIB\LIBC.LIB
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
|
||||
GSM 06.10 13 kbit/s RPE/LTP speech compression available
|
||||
--------------------------------------------------------
|
||||
|
||||
The Communications and Operating Systems Research Group (KBS) at the
|
||||
Technische Universitaet Berlin is currently working on a set of
|
||||
UNIX-based tools for computer-mediated telecooperation that will be
|
||||
made freely available.
|
||||
|
||||
As part of this effort we are publishing an implementation of the
|
||||
European GSM 06.10 provisional standard for full-rate speech
|
||||
transcoding, prI-ETS 300 036, which uses RPE/LTP (residual pulse
|
||||
excitation/long term prediction) coding at 13 kbit/s.
|
||||
|
||||
GSM 06.10 compresses frames of 160 13-bit samples (8 kHz sampling
|
||||
rate, i.e. a frame rate of 50 Hz) into 260 bits; for compatibility
|
||||
with typical UNIX applications, our implementation turns frames of 160
|
||||
16-bit linear samples into 33-byte frames (1650 Bytes/s).
|
||||
The quality of the algorithm is good enough for reliable speaker
|
||||
recognition; even music often survives transcoding in recognizable
|
||||
form (given the bandwidth limitations of 8 kHz sampling rate).
|
||||
|
||||
The interfaces offered are a front end modelled after compress(1), and
|
||||
a library API. Compression and decompression run faster than realtime
|
||||
on most SPARCstations. The implementation has been verified against the
|
||||
ETSI standard test patterns.
|
||||
|
||||
Jutta Degener (jutta@cs.tu-berlin.de)
|
||||
Carsten Bormann (cabo@cs.tu-berlin.de)
|
||||
|
||||
Communications and Operating Systems Research Group, TU Berlin
|
||||
Fax: +49.30.31425156, Phone: +49.30.31424315
|
||||
|
||||
--
|
||||
Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
Vendored
+235
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/*
|
||||
* See private.h for the more commonly used macro versions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
#define saturate(x) \
|
||||
((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x))
|
||||
|
||||
word gsm_add P2((a,b), word a, word b)
|
||||
{
|
||||
longword sum = (longword)a + (longword)b;
|
||||
return (word) saturate(sum);
|
||||
}
|
||||
|
||||
word gsm_sub P2((a,b), word a, word b)
|
||||
{
|
||||
longword diff = (longword)a - (longword)b;
|
||||
return (word) saturate(diff);
|
||||
}
|
||||
|
||||
word gsm_mult P2((a,b), word a, word b)
|
||||
{
|
||||
if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD;
|
||||
else return SASR( (longword)a * (longword)b, 15 );
|
||||
}
|
||||
|
||||
word gsm_mult_r P2((a,b), word a, word b)
|
||||
{
|
||||
if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD;
|
||||
else {
|
||||
longword prod = (longword)a * (longword)b + 16384;
|
||||
prod >>= 15;
|
||||
return prod & 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
word gsm_abs P1((a), word a)
|
||||
{
|
||||
return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a;
|
||||
}
|
||||
|
||||
longword gsm_L_mult P2((a,b),word a, word b)
|
||||
{
|
||||
assert( a != MIN_WORD || b != MIN_WORD );
|
||||
return ((longword)a * (longword)b) << 1;
|
||||
}
|
||||
|
||||
longword gsm_L_add P2((a,b), longword a, longword b)
|
||||
{
|
||||
if (a < 0) {
|
||||
if (b >= 0) return a + b;
|
||||
else {
|
||||
ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1);
|
||||
return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2;
|
||||
}
|
||||
}
|
||||
else if (b <= 0) return a + b;
|
||||
else {
|
||||
ulongword A = (ulongword)a + (ulongword)b;
|
||||
return A > MAX_LONGWORD ? MAX_LONGWORD : A;
|
||||
}
|
||||
}
|
||||
|
||||
longword gsm_L_sub P2((a,b), longword a, longword b)
|
||||
{
|
||||
if (a >= 0) {
|
||||
if (b >= 0) return a - b;
|
||||
else {
|
||||
/* a>=0, b<0 */
|
||||
|
||||
ulongword A = (ulongword)a + -(b + 1);
|
||||
return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1);
|
||||
}
|
||||
}
|
||||
else if (b <= 0) return a - b;
|
||||
else {
|
||||
/* a<0, b>0 */
|
||||
|
||||
ulongword A = (ulongword)-(a + 1) + b;
|
||||
return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char const bitoff[ 256 ] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
word gsm_norm P1((a), longword a )
|
||||
/*
|
||||
* the number of left shifts needed to normalize the 32 bit
|
||||
* variable L_var1 for positive values on the interval
|
||||
*
|
||||
* with minimum of
|
||||
* minimum of 1073741824 (01000000000000000000000000000000) and
|
||||
* maximum of 2147483647 (01111111111111111111111111111111)
|
||||
*
|
||||
*
|
||||
* and for negative values on the interval with
|
||||
* minimum of -2147483648 (-10000000000000000000000000000000) and
|
||||
* maximum of -1073741824 ( -1000000000000000000000000000000).
|
||||
*
|
||||
* in order to normalize the result, the following
|
||||
* operation must be done: L_norm_var1 = L_var1 << norm( L_var1 );
|
||||
*
|
||||
* (That's 'ffs', only from the left, not the right..)
|
||||
*/
|
||||
{
|
||||
assert(a != 0);
|
||||
|
||||
if (a < 0) {
|
||||
if (a <= -1073741824) return 0;
|
||||
a = ~a;
|
||||
}
|
||||
|
||||
return a & 0xffff0000
|
||||
? ( a & 0xff000000
|
||||
? -1 + bitoff[ 0xFF & (a >> 24) ]
|
||||
: 7 + bitoff[ 0xFF & (a >> 16) ] )
|
||||
: ( a & 0xff00
|
||||
? 15 + bitoff[ 0xFF & (a >> 8) ]
|
||||
: 23 + bitoff[ 0xFF & a ] );
|
||||
}
|
||||
|
||||
longword gsm_L_asl P2((a,n), longword a, int n)
|
||||
{
|
||||
if (n >= 32) return 0;
|
||||
if (n <= -32) return -(a < 0);
|
||||
if (n < 0) return gsm_L_asr(a, -n);
|
||||
return a << n;
|
||||
}
|
||||
|
||||
word gsm_asl P2((a,n), word a, int n)
|
||||
{
|
||||
if (n >= 16) return 0;
|
||||
if (n <= -16) return -(a < 0);
|
||||
if (n < 0) return gsm_asr(a, -n);
|
||||
return a << n;
|
||||
}
|
||||
|
||||
longword gsm_L_asr P2((a,n), longword a, int n)
|
||||
{
|
||||
if (n >= 32) return -(a < 0);
|
||||
if (n <= -32) return 0;
|
||||
if (n < 0) return a << -n;
|
||||
|
||||
# ifdef SASR
|
||||
return a >> n;
|
||||
# else
|
||||
if (a >= 0) return a >> n;
|
||||
else return -(longword)( -(ulongword)a >> n );
|
||||
# endif
|
||||
}
|
||||
|
||||
word gsm_asr P2((a,n), word a, int n)
|
||||
{
|
||||
if (n >= 16) return -(a < 0);
|
||||
if (n <= -16) return 0;
|
||||
if (n < 0) return a << -n;
|
||||
|
||||
# ifdef SASR
|
||||
return a >> n;
|
||||
# else
|
||||
if (a >= 0) return a >> n;
|
||||
else return -(word)( -(uword)a >> n );
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
* (From p. 46, end of section 4.2.5)
|
||||
*
|
||||
* NOTE: The following lines gives [sic] one correct implementation
|
||||
* of the div(num, denum) arithmetic operation. Compute div
|
||||
* which is the integer division of num by denum: with denum
|
||||
* >= num > 0
|
||||
*/
|
||||
|
||||
word gsm_div P2((num,denum), word num, word denum)
|
||||
{
|
||||
longword L_num = num;
|
||||
longword L_denum = denum;
|
||||
word div = 0;
|
||||
int k = 15;
|
||||
|
||||
/* The parameter num sometimes becomes zero.
|
||||
* Although this is explicitly guarded against in 4.2.5,
|
||||
* we assume that the result should then be zero as well.
|
||||
*/
|
||||
|
||||
/* assert(num != 0); */
|
||||
|
||||
assert(num >= 0 && denum >= num);
|
||||
if (num == 0)
|
||||
return 0;
|
||||
|
||||
while (k--) {
|
||||
div <<= 1;
|
||||
L_num <<= 1;
|
||||
|
||||
if (L_num >= L_denum) {
|
||||
L_num -= L_denum;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
return div;
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
//#ifdef HAS_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
//#else
|
||||
# include "proto.h"
|
||||
# include "string.h"
|
||||
//extern char * memcpy P((char *, char *, int));
|
||||
//#endif
|
||||
|
||||
#include "private.h"
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
/*
|
||||
* 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER
|
||||
*/
|
||||
|
||||
void Gsm_Coder P8((S,s,LARc,Nc,bc,Mc,xmaxc,xMc),
|
||||
|
||||
struct gsm_state * S,
|
||||
|
||||
word * s, /* [0..159] samples IN */
|
||||
|
||||
/*
|
||||
* The RPE-LTD coder works on a frame by frame basis. The length of
|
||||
* the frame is equal to 160 samples. Some computations are done
|
||||
* once per frame to produce at the output of the coder the
|
||||
* LARc[1..8] parameters which are the coded LAR coefficients and
|
||||
* also to realize the inverse filtering operation for the entire
|
||||
* frame (160 samples of signal d[0..159]). These parts produce at
|
||||
* the output of the coder:
|
||||
*/
|
||||
|
||||
word * LARc, /* [0..7] LAR coefficients OUT */
|
||||
|
||||
/*
|
||||
* Procedure 4.2.11 to 4.2.18 are to be executed four times per
|
||||
* frame. That means once for each sub-segment RPE-LTP analysis of
|
||||
* 40 samples. These parts produce at the output of the coder:
|
||||
*/
|
||||
|
||||
word * Nc, /* [0..3] LTP lag OUT */
|
||||
word * bc, /* [0..3] coded LTP gain OUT */
|
||||
word * Mc, /* [0..3] RPE grid selection OUT */
|
||||
word * xmaxc,/* [0..3] Coded maximum amplitude OUT */
|
||||
word * xMc /* [13*4] normalized RPE samples OUT */
|
||||
)
|
||||
{
|
||||
int k;
|
||||
word * dp = S->dp0 + 120; /* [ -120...-1 ] */
|
||||
word * dpp = dp; /* [ 0...39 ] */
|
||||
|
||||
static word e[50];
|
||||
|
||||
word so[160];
|
||||
|
||||
Gsm_Preprocess (S, s, so);
|
||||
Gsm_LPC_Analysis (S, so, LARc);
|
||||
Gsm_Short_Term_Analysis_Filter (S, LARc, so);
|
||||
|
||||
for (k = 0; k <= 3; k++, xMc += 13) {
|
||||
|
||||
Gsm_Long_Term_Predictor ( S,
|
||||
so+k*40, /* d [0..39] IN */
|
||||
dp, /* dp [-120..-1] IN */
|
||||
e + 5, /* e [0..39] OUT */
|
||||
dpp, /* dpp [0..39] OUT */
|
||||
Nc++,
|
||||
bc++);
|
||||
|
||||
Gsm_RPE_Encoding ( S,
|
||||
e + 5, /* e ][0..39][ IN/OUT */
|
||||
xmaxc++, Mc++, xMc );
|
||||
/*
|
||||
* Gsm_Update_of_reconstructed_short_time_residual_signal
|
||||
* ( dpp, e + 5, dp );
|
||||
*/
|
||||
|
||||
{ register int i;
|
||||
register longword ltmp;
|
||||
for (i = 0; i <= 39; i++)
|
||||
dp[ i ] = GSM_ADD( e[5 + i], dpp[i] );
|
||||
}
|
||||
dp += 40;
|
||||
dpp += 40;
|
||||
|
||||
}
|
||||
(void)memcpy( (char *)S->dp0, (char *)(S->dp0 + 160),
|
||||
120 * sizeof(*S->dp0) );
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
/* If NDEBUG _is_ defined and no debugging should be performed,
|
||||
* calls to functions in this module are #defined to nothing
|
||||
* in private.h.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "proto.h"
|
||||
|
||||
void gsm_debug_words P4( (name, from, to, ptr),
|
||||
char * name,
|
||||
int from,
|
||||
int to,
|
||||
word * ptr)
|
||||
{
|
||||
int nprinted = 0;
|
||||
|
||||
fprintf( stderr, "%s [%d .. %d]: ", name, from, to );
|
||||
while (from <= to) {
|
||||
fprintf(stderr, "%d ", ptr[ from ] );
|
||||
from++;
|
||||
if (nprinted++ >= 7) {
|
||||
nprinted = 0;
|
||||
if (from < to) putc('\n', stderr);
|
||||
}
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
|
||||
void gsm_debug_longwords P4( (name, from, to, ptr),
|
||||
char * name,
|
||||
int from,
|
||||
int to,
|
||||
longword * ptr)
|
||||
{
|
||||
int nprinted = 0;
|
||||
|
||||
fprintf( stderr, "%s [%d .. %d]: ", name, from, to );
|
||||
while (from <= to) {
|
||||
|
||||
fprintf(stderr, "%ld ", ptr[ from ] );
|
||||
from++;
|
||||
if (nprinted++ >= 7) {
|
||||
nprinted = 0;
|
||||
if (from < to) putc('\n', stderr);
|
||||
}
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
|
||||
void gsm_debug_longword P2( (name, value),
|
||||
char * name,
|
||||
longword value )
|
||||
{
|
||||
fprintf(stderr, "%s: %ld\n", name, (long)value );
|
||||
}
|
||||
|
||||
void gsm_debug_word P2( (name, value),
|
||||
char * name,
|
||||
word value )
|
||||
{
|
||||
fprintf(stderr, "%s: %ld\n", name, (long)value);
|
||||
}
|
||||
|
||||
#endif
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
/*
|
||||
* 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER
|
||||
*/
|
||||
|
||||
static void Postprocessing P2((S,s),
|
||||
struct gsm_state * S,
|
||||
register word * s)
|
||||
{
|
||||
register int k;
|
||||
register word msr = S->msr;
|
||||
register longword ltmp; /* for GSM_ADD */
|
||||
register word tmp;
|
||||
|
||||
for (k = 160; k--; s++) {
|
||||
tmp = GSM_MULT_R( msr, 28180 );
|
||||
msr = GSM_ADD(*s, tmp); /* Deemphasis */
|
||||
*s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */
|
||||
}
|
||||
S->msr = msr;
|
||||
}
|
||||
|
||||
void Gsm_Decoder P8((S,LARcr, Ncr,bcr,Mcr,xmaxcr,xMcr,s),
|
||||
struct gsm_state * S,
|
||||
|
||||
word * LARcr, /* [0..7] IN */
|
||||
|
||||
word * Ncr, /* [0..3] IN */
|
||||
word * bcr, /* [0..3] IN */
|
||||
word * Mcr, /* [0..3] IN */
|
||||
word * xmaxcr, /* [0..3] IN */
|
||||
word * xMcr, /* [0..13*4] IN */
|
||||
|
||||
word * s) /* [0..159] OUT */
|
||||
{
|
||||
int j, k;
|
||||
word erp[40], wt[160];
|
||||
word * drp = S->dp0 + 120;
|
||||
|
||||
for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) {
|
||||
|
||||
Gsm_RPE_Decoding( S, *xmaxcr, *Mcr, xMcr, erp );
|
||||
Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp );
|
||||
|
||||
for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ];
|
||||
}
|
||||
|
||||
Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s );
|
||||
Postprocessing(S, s);
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
//static char const ident[] = "$Header$";
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAS_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
# include "proto.h"
|
||||
extern char * memset P((char *, int, int));
|
||||
#endif
|
||||
|
||||
#ifdef HAS_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# ifdef HAS_MALLOC_H
|
||||
# include <malloc.h>
|
||||
# else
|
||||
extern char * malloc();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gsm.h"
|
||||
#include "private.h"
|
||||
#include "proto.h"
|
||||
|
||||
gsm gsm_create P0()
|
||||
{
|
||||
gsm r;
|
||||
|
||||
r = (gsm)malloc(sizeof(struct gsm_state));
|
||||
if (!r) return r;
|
||||
|
||||
memset((char *)r, 0, sizeof(*r));
|
||||
r->nrp = 40;
|
||||
|
||||
return r;
|
||||
}
|
||||
+361
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
int gsm_decode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target)
|
||||
{
|
||||
word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4];
|
||||
|
||||
#ifdef WAV49
|
||||
if (s->wav_fmt) {
|
||||
|
||||
uword sr = 0;
|
||||
|
||||
s->frame_index = !s->frame_index;
|
||||
if (s->frame_index) {
|
||||
|
||||
sr = *c++;
|
||||
LARc[0] = sr & 0x3f; sr >>= 6;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[1] = sr & 0x3f; sr >>= 6;
|
||||
sr |= (uword)*c++ << 4;
|
||||
LARc[2] = sr & 0x1f; sr >>= 5;
|
||||
LARc[3] = sr & 0x1f; sr >>= 5;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[4] = sr & 0xf; sr >>= 4;
|
||||
LARc[5] = sr & 0xf; sr >>= 4;
|
||||
sr |= (uword)*c++ << 2; /* 5 */
|
||||
LARc[6] = sr & 0x7; sr >>= 3;
|
||||
LARc[7] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[0] = sr & 0x7f; sr >>= 7;
|
||||
bc[0] = sr & 0x3; sr >>= 2;
|
||||
Mc[0] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[0] = sr & 0x3f; sr >>= 6;
|
||||
xmc[0] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[1] = sr & 0x7; sr >>= 3;
|
||||
xmc[2] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[3] = sr & 0x7; sr >>= 3;
|
||||
xmc[4] = sr & 0x7; sr >>= 3;
|
||||
xmc[5] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 10 */
|
||||
xmc[6] = sr & 0x7; sr >>= 3;
|
||||
xmc[7] = sr & 0x7; sr >>= 3;
|
||||
xmc[8] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[9] = sr & 0x7; sr >>= 3;
|
||||
xmc[10] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[11] = sr & 0x7; sr >>= 3;
|
||||
xmc[12] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[1] = sr & 0x7f; sr >>= 7;
|
||||
bc[1] = sr & 0x3; sr >>= 2;
|
||||
Mc[1] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[1] = sr & 0x3f; sr >>= 6;
|
||||
xmc[13] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 15 */
|
||||
xmc[14] = sr & 0x7; sr >>= 3;
|
||||
xmc[15] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[16] = sr & 0x7; sr >>= 3;
|
||||
xmc[17] = sr & 0x7; sr >>= 3;
|
||||
xmc[18] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[19] = sr & 0x7; sr >>= 3;
|
||||
xmc[20] = sr & 0x7; sr >>= 3;
|
||||
xmc[21] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[22] = sr & 0x7; sr >>= 3;
|
||||
xmc[23] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[24] = sr & 0x7; sr >>= 3;
|
||||
xmc[25] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4; /* 20 */
|
||||
Nc[2] = sr & 0x7f; sr >>= 7;
|
||||
bc[2] = sr & 0x3; sr >>= 2;
|
||||
Mc[2] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[2] = sr & 0x3f; sr >>= 6;
|
||||
xmc[26] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[27] = sr & 0x7; sr >>= 3;
|
||||
xmc[28] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[29] = sr & 0x7; sr >>= 3;
|
||||
xmc[30] = sr & 0x7; sr >>= 3;
|
||||
xmc[31] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[32] = sr & 0x7; sr >>= 3;
|
||||
xmc[33] = sr & 0x7; sr >>= 3;
|
||||
xmc[34] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 25 */
|
||||
xmc[35] = sr & 0x7; sr >>= 3;
|
||||
xmc[36] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[37] = sr & 0x7; sr >>= 3;
|
||||
xmc[38] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[3] = sr & 0x7f; sr >>= 7;
|
||||
bc[3] = sr & 0x3; sr >>= 2;
|
||||
Mc[3] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[3] = sr & 0x3f; sr >>= 6;
|
||||
xmc[39] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[40] = sr & 0x7; sr >>= 3;
|
||||
xmc[41] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2; /* 30 */
|
||||
xmc[42] = sr & 0x7; sr >>= 3;
|
||||
xmc[43] = sr & 0x7; sr >>= 3;
|
||||
xmc[44] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[45] = sr & 0x7; sr >>= 3;
|
||||
xmc[46] = sr & 0x7; sr >>= 3;
|
||||
xmc[47] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[48] = sr & 0x7; sr >>= 3;
|
||||
xmc[49] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[50] = sr & 0x7; sr >>= 3;
|
||||
xmc[51] = sr & 0x7; sr >>= 3;
|
||||
|
||||
s->frame_chain = sr & 0xf;
|
||||
}
|
||||
else {
|
||||
sr = s->frame_chain;
|
||||
sr |= (uword)*c++ << 4; /* 1 */
|
||||
LARc[0] = sr & 0x3f; sr >>= 6;
|
||||
LARc[1] = sr & 0x3f; sr >>= 6;
|
||||
sr = *c++;
|
||||
LARc[2] = sr & 0x1f; sr >>= 5;
|
||||
sr |= (uword)*c++ << 3;
|
||||
LARc[3] = sr & 0x1f; sr >>= 5;
|
||||
LARc[4] = sr & 0xf; sr >>= 4;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[5] = sr & 0xf; sr >>= 4;
|
||||
LARc[6] = sr & 0x7; sr >>= 3;
|
||||
LARc[7] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 5 */
|
||||
Nc[0] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[0] = sr & 0x3; sr >>= 2;
|
||||
Mc[0] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[0] = sr & 0x3f; sr >>= 6;
|
||||
xmc[0] = sr & 0x7; sr >>= 3;
|
||||
xmc[1] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[2] = sr & 0x7; sr >>= 3;
|
||||
xmc[3] = sr & 0x7; sr >>= 3;
|
||||
xmc[4] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[5] = sr & 0x7; sr >>= 3;
|
||||
xmc[6] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2; /* 10 */
|
||||
xmc[7] = sr & 0x7; sr >>= 3;
|
||||
xmc[8] = sr & 0x7; sr >>= 3;
|
||||
xmc[9] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[10] = sr & 0x7; sr >>= 3;
|
||||
xmc[11] = sr & 0x7; sr >>= 3;
|
||||
xmc[12] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[1] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[1] = sr & 0x3; sr >>= 2;
|
||||
Mc[1] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[1] = sr & 0x3f; sr >>= 6;
|
||||
xmc[13] = sr & 0x7; sr >>= 3;
|
||||
xmc[14] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 15 */
|
||||
xmc[15] = sr & 0x7; sr >>= 3;
|
||||
xmc[16] = sr & 0x7; sr >>= 3;
|
||||
xmc[17] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[18] = sr & 0x7; sr >>= 3;
|
||||
xmc[19] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[20] = sr & 0x7; sr >>= 3;
|
||||
xmc[21] = sr & 0x7; sr >>= 3;
|
||||
xmc[22] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[23] = sr & 0x7; sr >>= 3;
|
||||
xmc[24] = sr & 0x7; sr >>= 3;
|
||||
xmc[25] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[2] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1; /* 20 */
|
||||
bc[2] = sr & 0x3; sr >>= 2;
|
||||
Mc[2] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[2] = sr & 0x3f; sr >>= 6;
|
||||
xmc[26] = sr & 0x7; sr >>= 3;
|
||||
xmc[27] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[28] = sr & 0x7; sr >>= 3;
|
||||
xmc[29] = sr & 0x7; sr >>= 3;
|
||||
xmc[30] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[31] = sr & 0x7; sr >>= 3;
|
||||
xmc[32] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[33] = sr & 0x7; sr >>= 3;
|
||||
xmc[34] = sr & 0x7; sr >>= 3;
|
||||
xmc[35] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 25 */
|
||||
xmc[36] = sr & 0x7; sr >>= 3;
|
||||
xmc[37] = sr & 0x7; sr >>= 3;
|
||||
xmc[38] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[3] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[3] = sr & 0x3; sr >>= 2;
|
||||
Mc[3] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[3] = sr & 0x3f; sr >>= 6;
|
||||
xmc[39] = sr & 0x7; sr >>= 3;
|
||||
xmc[40] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[41] = sr & 0x7; sr >>= 3;
|
||||
xmc[42] = sr & 0x7; sr >>= 3;
|
||||
xmc[43] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 30 */
|
||||
xmc[44] = sr & 0x7; sr >>= 3;
|
||||
xmc[45] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[46] = sr & 0x7; sr >>= 3;
|
||||
xmc[47] = sr & 0x7; sr >>= 3;
|
||||
xmc[48] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[49] = sr & 0x7; sr >>= 3;
|
||||
xmc[50] = sr & 0x7; sr >>= 3;
|
||||
xmc[51] = sr & 0x7; sr >>= 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* GSM_MAGIC = (*c >> 4) & 0xF; */
|
||||
|
||||
if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1;
|
||||
|
||||
LARc[0] = (*c++ & 0xF) << 2; /* 1 */
|
||||
LARc[0] |= (*c >> 6) & 0x3;
|
||||
LARc[1] = *c++ & 0x3F;
|
||||
LARc[2] = (*c >> 3) & 0x1F;
|
||||
LARc[3] = (*c++ & 0x7) << 2;
|
||||
LARc[3] |= (*c >> 6) & 0x3;
|
||||
LARc[4] = (*c >> 2) & 0xF;
|
||||
LARc[5] = (*c++ & 0x3) << 2;
|
||||
LARc[5] |= (*c >> 6) & 0x3;
|
||||
LARc[6] = (*c >> 3) & 0x7;
|
||||
LARc[7] = *c++ & 0x7;
|
||||
Nc[0] = (*c >> 1) & 0x7F;
|
||||
bc[0] = (*c++ & 0x1) << 1;
|
||||
bc[0] |= (*c >> 7) & 0x1;
|
||||
Mc[0] = (*c >> 5) & 0x3;
|
||||
xmaxc[0] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[0] |= (*c >> 7) & 0x1;
|
||||
xmc[0] = (*c >> 4) & 0x7;
|
||||
xmc[1] = (*c >> 1) & 0x7;
|
||||
xmc[2] = (*c++ & 0x1) << 2;
|
||||
xmc[2] |= (*c >> 6) & 0x3;
|
||||
xmc[3] = (*c >> 3) & 0x7;
|
||||
xmc[4] = *c++ & 0x7;
|
||||
xmc[5] = (*c >> 5) & 0x7;
|
||||
xmc[6] = (*c >> 2) & 0x7;
|
||||
xmc[7] = (*c++ & 0x3) << 1; /* 10 */
|
||||
xmc[7] |= (*c >> 7) & 0x1;
|
||||
xmc[8] = (*c >> 4) & 0x7;
|
||||
xmc[9] = (*c >> 1) & 0x7;
|
||||
xmc[10] = (*c++ & 0x1) << 2;
|
||||
xmc[10] |= (*c >> 6) & 0x3;
|
||||
xmc[11] = (*c >> 3) & 0x7;
|
||||
xmc[12] = *c++ & 0x7;
|
||||
Nc[1] = (*c >> 1) & 0x7F;
|
||||
bc[1] = (*c++ & 0x1) << 1;
|
||||
bc[1] |= (*c >> 7) & 0x1;
|
||||
Mc[1] = (*c >> 5) & 0x3;
|
||||
xmaxc[1] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[1] |= (*c >> 7) & 0x1;
|
||||
xmc[13] = (*c >> 4) & 0x7;
|
||||
xmc[14] = (*c >> 1) & 0x7;
|
||||
xmc[15] = (*c++ & 0x1) << 2;
|
||||
xmc[15] |= (*c >> 6) & 0x3;
|
||||
xmc[16] = (*c >> 3) & 0x7;
|
||||
xmc[17] = *c++ & 0x7;
|
||||
xmc[18] = (*c >> 5) & 0x7;
|
||||
xmc[19] = (*c >> 2) & 0x7;
|
||||
xmc[20] = (*c++ & 0x3) << 1;
|
||||
xmc[20] |= (*c >> 7) & 0x1;
|
||||
xmc[21] = (*c >> 4) & 0x7;
|
||||
xmc[22] = (*c >> 1) & 0x7;
|
||||
xmc[23] = (*c++ & 0x1) << 2;
|
||||
xmc[23] |= (*c >> 6) & 0x3;
|
||||
xmc[24] = (*c >> 3) & 0x7;
|
||||
xmc[25] = *c++ & 0x7;
|
||||
Nc[2] = (*c >> 1) & 0x7F;
|
||||
bc[2] = (*c++ & 0x1) << 1; /* 20 */
|
||||
bc[2] |= (*c >> 7) & 0x1;
|
||||
Mc[2] = (*c >> 5) & 0x3;
|
||||
xmaxc[2] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[2] |= (*c >> 7) & 0x1;
|
||||
xmc[26] = (*c >> 4) & 0x7;
|
||||
xmc[27] = (*c >> 1) & 0x7;
|
||||
xmc[28] = (*c++ & 0x1) << 2;
|
||||
xmc[28] |= (*c >> 6) & 0x3;
|
||||
xmc[29] = (*c >> 3) & 0x7;
|
||||
xmc[30] = *c++ & 0x7;
|
||||
xmc[31] = (*c >> 5) & 0x7;
|
||||
xmc[32] = (*c >> 2) & 0x7;
|
||||
xmc[33] = (*c++ & 0x3) << 1;
|
||||
xmc[33] |= (*c >> 7) & 0x1;
|
||||
xmc[34] = (*c >> 4) & 0x7;
|
||||
xmc[35] = (*c >> 1) & 0x7;
|
||||
xmc[36] = (*c++ & 0x1) << 2;
|
||||
xmc[36] |= (*c >> 6) & 0x3;
|
||||
xmc[37] = (*c >> 3) & 0x7;
|
||||
xmc[38] = *c++ & 0x7;
|
||||
Nc[3] = (*c >> 1) & 0x7F;
|
||||
bc[3] = (*c++ & 0x1) << 1;
|
||||
bc[3] |= (*c >> 7) & 0x1;
|
||||
Mc[3] = (*c >> 5) & 0x3;
|
||||
xmaxc[3] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[3] |= (*c >> 7) & 0x1;
|
||||
xmc[39] = (*c >> 4) & 0x7;
|
||||
xmc[40] = (*c >> 1) & 0x7;
|
||||
xmc[41] = (*c++ & 0x1) << 2;
|
||||
xmc[41] |= (*c >> 6) & 0x3;
|
||||
xmc[42] = (*c >> 3) & 0x7;
|
||||
xmc[43] = *c++ & 0x7; /* 30 */
|
||||
xmc[44] = (*c >> 5) & 0x7;
|
||||
xmc[45] = (*c >> 2) & 0x7;
|
||||
xmc[46] = (*c++ & 0x3) << 1;
|
||||
xmc[46] |= (*c >> 7) & 0x1;
|
||||
xmc[47] = (*c >> 4) & 0x7;
|
||||
xmc[48] = (*c >> 1) & 0x7;
|
||||
xmc[49] = (*c++ & 0x1) << 2;
|
||||
xmc[49] |= (*c >> 6) & 0x3;
|
||||
xmc[50] = (*c >> 3) & 0x7;
|
||||
xmc[51] = *c & 0x7; /* 33 */
|
||||
}
|
||||
|
||||
Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "gsm.h"
|
||||
#include "config.h"
|
||||
#include "proto.h"
|
||||
|
||||
#ifdef HAS_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# ifdef HAS_MALLOC_H
|
||||
# include <malloc.h>
|
||||
# else
|
||||
extern void free();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void gsm_destroy P1((S), gsm S)
|
||||
{
|
||||
if (S) free((char *)S);
|
||||
}
|
||||
+451
@@ -0,0 +1,451 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "private.h"
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
void gsm_encode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c)
|
||||
{
|
||||
word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4];
|
||||
|
||||
Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc);
|
||||
|
||||
|
||||
/* variable size
|
||||
|
||||
GSM_MAGIC 4
|
||||
|
||||
LARc[0] 6
|
||||
LARc[1] 6
|
||||
LARc[2] 5
|
||||
LARc[3] 5
|
||||
LARc[4] 4
|
||||
LARc[5] 4
|
||||
LARc[6] 3
|
||||
LARc[7] 3
|
||||
|
||||
Nc[0] 7
|
||||
bc[0] 2
|
||||
Mc[0] 2
|
||||
xmaxc[0] 6
|
||||
xmc[0] 3
|
||||
xmc[1] 3
|
||||
xmc[2] 3
|
||||
xmc[3] 3
|
||||
xmc[4] 3
|
||||
xmc[5] 3
|
||||
xmc[6] 3
|
||||
xmc[7] 3
|
||||
xmc[8] 3
|
||||
xmc[9] 3
|
||||
xmc[10] 3
|
||||
xmc[11] 3
|
||||
xmc[12] 3
|
||||
|
||||
Nc[1] 7
|
||||
bc[1] 2
|
||||
Mc[1] 2
|
||||
xmaxc[1] 6
|
||||
xmc[13] 3
|
||||
xmc[14] 3
|
||||
xmc[15] 3
|
||||
xmc[16] 3
|
||||
xmc[17] 3
|
||||
xmc[18] 3
|
||||
xmc[19] 3
|
||||
xmc[20] 3
|
||||
xmc[21] 3
|
||||
xmc[22] 3
|
||||
xmc[23] 3
|
||||
xmc[24] 3
|
||||
xmc[25] 3
|
||||
|
||||
Nc[2] 7
|
||||
bc[2] 2
|
||||
Mc[2] 2
|
||||
xmaxc[2] 6
|
||||
xmc[26] 3
|
||||
xmc[27] 3
|
||||
xmc[28] 3
|
||||
xmc[29] 3
|
||||
xmc[30] 3
|
||||
xmc[31] 3
|
||||
xmc[32] 3
|
||||
xmc[33] 3
|
||||
xmc[34] 3
|
||||
xmc[35] 3
|
||||
xmc[36] 3
|
||||
xmc[37] 3
|
||||
xmc[38] 3
|
||||
|
||||
Nc[3] 7
|
||||
bc[3] 2
|
||||
Mc[3] 2
|
||||
xmaxc[3] 6
|
||||
xmc[39] 3
|
||||
xmc[40] 3
|
||||
xmc[41] 3
|
||||
xmc[42] 3
|
||||
xmc[43] 3
|
||||
xmc[44] 3
|
||||
xmc[45] 3
|
||||
xmc[46] 3
|
||||
xmc[47] 3
|
||||
xmc[48] 3
|
||||
xmc[49] 3
|
||||
xmc[50] 3
|
||||
xmc[51] 3
|
||||
*/
|
||||
|
||||
#ifdef WAV49
|
||||
|
||||
if (s->wav_fmt) {
|
||||
s->frame_index = !s->frame_index;
|
||||
if (s->frame_index) {
|
||||
|
||||
uword sr;
|
||||
|
||||
sr = 0;
|
||||
sr = sr >> 6 | LARc[0] << 10;
|
||||
sr = sr >> 6 | LARc[1] << 10;
|
||||
*c++ = sr >> 4;
|
||||
sr = sr >> 5 | LARc[2] << 11;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 5 | LARc[3] << 11;
|
||||
sr = sr >> 4 | LARc[4] << 12;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 4 | LARc[5] << 12;
|
||||
sr = sr >> 3 | LARc[6] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | LARc[7] << 13;
|
||||
sr = sr >> 7 | Nc[0] << 9;
|
||||
*c++ = sr >> 5;
|
||||
sr = sr >> 2 | bc[0] << 14;
|
||||
sr = sr >> 2 | Mc[0] << 14;
|
||||
sr = sr >> 6 | xmaxc[0] << 10;
|
||||
*c++ = sr >> 3;
|
||||
sr = sr >> 3 | xmc[0] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[1] << 13;
|
||||
sr = sr >> 3 | xmc[2] << 13;
|
||||
sr = sr >> 3 | xmc[3] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[4] << 13;
|
||||
sr = sr >> 3 | xmc[5] << 13;
|
||||
sr = sr >> 3 | xmc[6] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[7] << 13;
|
||||
sr = sr >> 3 | xmc[8] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[9] << 13;
|
||||
sr = sr >> 3 | xmc[10] << 13;
|
||||
sr = sr >> 3 | xmc[11] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[12] << 13;
|
||||
sr = sr >> 7 | Nc[1] << 9;
|
||||
*c++ = sr >> 5;
|
||||
sr = sr >> 2 | bc[1] << 14;
|
||||
sr = sr >> 2 | Mc[1] << 14;
|
||||
sr = sr >> 6 | xmaxc[1] << 10;
|
||||
*c++ = sr >> 3;
|
||||
sr = sr >> 3 | xmc[13] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[14] << 13;
|
||||
sr = sr >> 3 | xmc[15] << 13;
|
||||
sr = sr >> 3 | xmc[16] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[17] << 13;
|
||||
sr = sr >> 3 | xmc[18] << 13;
|
||||
sr = sr >> 3 | xmc[19] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[20] << 13;
|
||||
sr = sr >> 3 | xmc[21] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[22] << 13;
|
||||
sr = sr >> 3 | xmc[23] << 13;
|
||||
sr = sr >> 3 | xmc[24] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[25] << 13;
|
||||
sr = sr >> 7 | Nc[2] << 9;
|
||||
*c++ = sr >> 5;
|
||||
sr = sr >> 2 | bc[2] << 14;
|
||||
sr = sr >> 2 | Mc[2] << 14;
|
||||
sr = sr >> 6 | xmaxc[2] << 10;
|
||||
*c++ = sr >> 3;
|
||||
sr = sr >> 3 | xmc[26] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[27] << 13;
|
||||
sr = sr >> 3 | xmc[28] << 13;
|
||||
sr = sr >> 3 | xmc[29] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[30] << 13;
|
||||
sr = sr >> 3 | xmc[31] << 13;
|
||||
sr = sr >> 3 | xmc[32] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[33] << 13;
|
||||
sr = sr >> 3 | xmc[34] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[35] << 13;
|
||||
sr = sr >> 3 | xmc[36] << 13;
|
||||
sr = sr >> 3 | xmc[37] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[38] << 13;
|
||||
sr = sr >> 7 | Nc[3] << 9;
|
||||
*c++ = sr >> 5;
|
||||
sr = sr >> 2 | bc[3] << 14;
|
||||
sr = sr >> 2 | Mc[3] << 14;
|
||||
sr = sr >> 6 | xmaxc[3] << 10;
|
||||
*c++ = sr >> 3;
|
||||
sr = sr >> 3 | xmc[39] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[40] << 13;
|
||||
sr = sr >> 3 | xmc[41] << 13;
|
||||
sr = sr >> 3 | xmc[42] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[43] << 13;
|
||||
sr = sr >> 3 | xmc[44] << 13;
|
||||
sr = sr >> 3 | xmc[45] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[46] << 13;
|
||||
sr = sr >> 3 | xmc[47] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[48] << 13;
|
||||
sr = sr >> 3 | xmc[49] << 13;
|
||||
sr = sr >> 3 | xmc[50] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[51] << 13;
|
||||
sr = sr >> 4;
|
||||
*c = sr >> 8;
|
||||
s->frame_chain = *c;
|
||||
}
|
||||
else {
|
||||
uword sr;
|
||||
|
||||
sr = 0;
|
||||
sr = sr >> 4 | s->frame_chain << 12;
|
||||
sr = sr >> 6 | LARc[0] << 10;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 6 | LARc[1] << 10;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 5 | LARc[2] << 11;
|
||||
sr = sr >> 5 | LARc[3] << 11;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 4 | LARc[4] << 12;
|
||||
sr = sr >> 4 | LARc[5] << 12;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | LARc[6] << 13;
|
||||
sr = sr >> 3 | LARc[7] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 7 | Nc[0] << 9;
|
||||
sr = sr >> 2 | bc[0] << 14;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 2 | Mc[0] << 14;
|
||||
sr = sr >> 6 | xmaxc[0] << 10;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[0] << 13;
|
||||
sr = sr >> 3 | xmc[1] << 13;
|
||||
sr = sr >> 3 | xmc[2] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[3] << 13;
|
||||
sr = sr >> 3 | xmc[4] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[5] << 13;
|
||||
sr = sr >> 3 | xmc[6] << 13;
|
||||
sr = sr >> 3 | xmc[7] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[8] << 13;
|
||||
sr = sr >> 3 | xmc[9] << 13;
|
||||
sr = sr >> 3 | xmc[10] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[11] << 13;
|
||||
sr = sr >> 3 | xmc[12] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 7 | Nc[1] << 9;
|
||||
sr = sr >> 2 | bc[1] << 14;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 2 | Mc[1] << 14;
|
||||
sr = sr >> 6 | xmaxc[1] << 10;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[13] << 13;
|
||||
sr = sr >> 3 | xmc[14] << 13;
|
||||
sr = sr >> 3 | xmc[15] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[16] << 13;
|
||||
sr = sr >> 3 | xmc[17] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[18] << 13;
|
||||
sr = sr >> 3 | xmc[19] << 13;
|
||||
sr = sr >> 3 | xmc[20] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[21] << 13;
|
||||
sr = sr >> 3 | xmc[22] << 13;
|
||||
sr = sr >> 3 | xmc[23] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[24] << 13;
|
||||
sr = sr >> 3 | xmc[25] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 7 | Nc[2] << 9;
|
||||
sr = sr >> 2 | bc[2] << 14;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 2 | Mc[2] << 14;
|
||||
sr = sr >> 6 | xmaxc[2] << 10;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[26] << 13;
|
||||
sr = sr >> 3 | xmc[27] << 13;
|
||||
sr = sr >> 3 | xmc[28] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[29] << 13;
|
||||
sr = sr >> 3 | xmc[30] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[31] << 13;
|
||||
sr = sr >> 3 | xmc[32] << 13;
|
||||
sr = sr >> 3 | xmc[33] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[34] << 13;
|
||||
sr = sr >> 3 | xmc[35] << 13;
|
||||
sr = sr >> 3 | xmc[36] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[37] << 13;
|
||||
sr = sr >> 3 | xmc[38] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 7 | Nc[3] << 9;
|
||||
sr = sr >> 2 | bc[3] << 14;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 2 | Mc[3] << 14;
|
||||
sr = sr >> 6 | xmaxc[3] << 10;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[39] << 13;
|
||||
sr = sr >> 3 | xmc[40] << 13;
|
||||
sr = sr >> 3 | xmc[41] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[42] << 13;
|
||||
sr = sr >> 3 | xmc[43] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[44] << 13;
|
||||
sr = sr >> 3 | xmc[45] << 13;
|
||||
sr = sr >> 3 | xmc[46] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[47] << 13;
|
||||
sr = sr >> 3 | xmc[48] << 13;
|
||||
sr = sr >> 3 | xmc[49] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[50] << 13;
|
||||
sr = sr >> 3 | xmc[51] << 13;
|
||||
*c++ = sr >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
#endif /* WAV49 */
|
||||
{
|
||||
|
||||
*c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */
|
||||
| ((LARc[0] >> 2) & 0xF);
|
||||
*c++ = ((LARc[0] & 0x3) << 6)
|
||||
| (LARc[1] & 0x3F);
|
||||
*c++ = ((LARc[2] & 0x1F) << 3)
|
||||
| ((LARc[3] >> 2) & 0x7);
|
||||
*c++ = ((LARc[3] & 0x3) << 6)
|
||||
| ((LARc[4] & 0xF) << 2)
|
||||
| ((LARc[5] >> 2) & 0x3);
|
||||
*c++ = ((LARc[5] & 0x3) << 6)
|
||||
| ((LARc[6] & 0x7) << 3)
|
||||
| (LARc[7] & 0x7);
|
||||
*c++ = ((Nc[0] & 0x7F) << 1)
|
||||
| ((bc[0] >> 1) & 0x1);
|
||||
*c++ = ((bc[0] & 0x1) << 7)
|
||||
| ((Mc[0] & 0x3) << 5)
|
||||
| ((xmaxc[0] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[0] & 0x1) << 7)
|
||||
| ((xmc[0] & 0x7) << 4)
|
||||
| ((xmc[1] & 0x7) << 1)
|
||||
| ((xmc[2] >> 2) & 0x1);
|
||||
*c++ = ((xmc[2] & 0x3) << 6)
|
||||
| ((xmc[3] & 0x7) << 3)
|
||||
| (xmc[4] & 0x7);
|
||||
*c++ = ((xmc[5] & 0x7) << 5) /* 10 */
|
||||
| ((xmc[6] & 0x7) << 2)
|
||||
| ((xmc[7] >> 1) & 0x3);
|
||||
*c++ = ((xmc[7] & 0x1) << 7)
|
||||
| ((xmc[8] & 0x7) << 4)
|
||||
| ((xmc[9] & 0x7) << 1)
|
||||
| ((xmc[10] >> 2) & 0x1);
|
||||
*c++ = ((xmc[10] & 0x3) << 6)
|
||||
| ((xmc[11] & 0x7) << 3)
|
||||
| (xmc[12] & 0x7);
|
||||
*c++ = ((Nc[1] & 0x7F) << 1)
|
||||
| ((bc[1] >> 1) & 0x1);
|
||||
*c++ = ((bc[1] & 0x1) << 7)
|
||||
| ((Mc[1] & 0x3) << 5)
|
||||
| ((xmaxc[1] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[1] & 0x1) << 7)
|
||||
| ((xmc[13] & 0x7) << 4)
|
||||
| ((xmc[14] & 0x7) << 1)
|
||||
| ((xmc[15] >> 2) & 0x1);
|
||||
*c++ = ((xmc[15] & 0x3) << 6)
|
||||
| ((xmc[16] & 0x7) << 3)
|
||||
| (xmc[17] & 0x7);
|
||||
*c++ = ((xmc[18] & 0x7) << 5)
|
||||
| ((xmc[19] & 0x7) << 2)
|
||||
| ((xmc[20] >> 1) & 0x3);
|
||||
*c++ = ((xmc[20] & 0x1) << 7)
|
||||
| ((xmc[21] & 0x7) << 4)
|
||||
| ((xmc[22] & 0x7) << 1)
|
||||
| ((xmc[23] >> 2) & 0x1);
|
||||
*c++ = ((xmc[23] & 0x3) << 6)
|
||||
| ((xmc[24] & 0x7) << 3)
|
||||
| (xmc[25] & 0x7);
|
||||
*c++ = ((Nc[2] & 0x7F) << 1) /* 20 */
|
||||
| ((bc[2] >> 1) & 0x1);
|
||||
*c++ = ((bc[2] & 0x1) << 7)
|
||||
| ((Mc[2] & 0x3) << 5)
|
||||
| ((xmaxc[2] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[2] & 0x1) << 7)
|
||||
| ((xmc[26] & 0x7) << 4)
|
||||
| ((xmc[27] & 0x7) << 1)
|
||||
| ((xmc[28] >> 2) & 0x1);
|
||||
*c++ = ((xmc[28] & 0x3) << 6)
|
||||
| ((xmc[29] & 0x7) << 3)
|
||||
| (xmc[30] & 0x7);
|
||||
*c++ = ((xmc[31] & 0x7) << 5)
|
||||
| ((xmc[32] & 0x7) << 2)
|
||||
| ((xmc[33] >> 1) & 0x3);
|
||||
*c++ = ((xmc[33] & 0x1) << 7)
|
||||
| ((xmc[34] & 0x7) << 4)
|
||||
| ((xmc[35] & 0x7) << 1)
|
||||
| ((xmc[36] >> 2) & 0x1);
|
||||
*c++ = ((xmc[36] & 0x3) << 6)
|
||||
| ((xmc[37] & 0x7) << 3)
|
||||
| (xmc[38] & 0x7);
|
||||
*c++ = ((Nc[3] & 0x7F) << 1)
|
||||
| ((bc[3] >> 1) & 0x1);
|
||||
*c++ = ((bc[3] & 0x1) << 7)
|
||||
| ((Mc[3] & 0x3) << 5)
|
||||
| ((xmaxc[3] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[3] & 0x1) << 7)
|
||||
| ((xmc[39] & 0x7) << 4)
|
||||
| ((xmc[40] & 0x7) << 1)
|
||||
| ((xmc[41] >> 2) & 0x1);
|
||||
*c++ = ((xmc[41] & 0x3) << 6) /* 30 */
|
||||
| ((xmc[42] & 0x7) << 3)
|
||||
| (xmc[43] & 0x7);
|
||||
*c++ = ((xmc[44] & 0x7) << 5)
|
||||
| ((xmc[45] & 0x7) << 2)
|
||||
| ((xmc[46] >> 1) & 0x3);
|
||||
*c++ = ((xmc[46] & 0x1) << 7)
|
||||
| ((xmc[47] & 0x7) << 4)
|
||||
| ((xmc[48] & 0x7) << 1)
|
||||
| ((xmc[49] >> 2) & 0x1);
|
||||
*c++ = ((xmc[49] & 0x3) << 6)
|
||||
| ((xmc[50] & 0x7) << 3)
|
||||
| (xmc[51] & 0x7);
|
||||
|
||||
}
|
||||
}
|
||||
+417
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "private.h"
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
int gsm_explode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target)
|
||||
{
|
||||
# define LARc target
|
||||
# define Nc *((gsm_signal (*) [17])(target + 8))
|
||||
# define bc *((gsm_signal (*) [17])(target + 9))
|
||||
# define Mc *((gsm_signal (*) [17])(target + 10))
|
||||
# define xmaxc *((gsm_signal (*) [17])(target + 11))
|
||||
|
||||
|
||||
#ifdef WAV49
|
||||
if (s->wav_fmt) {
|
||||
|
||||
uword sr = 0;
|
||||
|
||||
if (s->frame_index == 1) {
|
||||
|
||||
sr = *c++;
|
||||
LARc[0] = sr & 0x3f; sr >>= 6;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[1] = sr & 0x3f; sr >>= 6;
|
||||
sr |= (uword)*c++ << 4;
|
||||
LARc[2] = sr & 0x1f; sr >>= 5;
|
||||
LARc[3] = sr & 0x1f; sr >>= 5;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[4] = sr & 0xf; sr >>= 4;
|
||||
LARc[5] = sr & 0xf; sr >>= 4;
|
||||
sr |= (uword)*c++ << 2; /* 5 */
|
||||
LARc[6] = sr & 0x7; sr >>= 3;
|
||||
LARc[7] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[0] = sr & 0x7f; sr >>= 7;
|
||||
bc[0] = sr & 0x3; sr >>= 2;
|
||||
Mc[0] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[0] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (target + 12)
|
||||
xmc[0] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[1] = sr & 0x7; sr >>= 3;
|
||||
xmc[2] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[3] = sr & 0x7; sr >>= 3;
|
||||
xmc[4] = sr & 0x7; sr >>= 3;
|
||||
xmc[5] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 10 */
|
||||
xmc[6] = sr & 0x7; sr >>= 3;
|
||||
xmc[7] = sr & 0x7; sr >>= 3;
|
||||
xmc[8] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[9] = sr & 0x7; sr >>= 3;
|
||||
xmc[10] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[11] = sr & 0x7; sr >>= 3;
|
||||
xmc[12] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[1] = sr & 0x7f; sr >>= 7;
|
||||
bc[1] = sr & 0x3; sr >>= 2;
|
||||
Mc[1] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[1] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (target + 29 - 13)
|
||||
|
||||
xmc[13] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 15 */
|
||||
xmc[14] = sr & 0x7; sr >>= 3;
|
||||
xmc[15] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[16] = sr & 0x7; sr >>= 3;
|
||||
xmc[17] = sr & 0x7; sr >>= 3;
|
||||
xmc[18] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[19] = sr & 0x7; sr >>= 3;
|
||||
xmc[20] = sr & 0x7; sr >>= 3;
|
||||
xmc[21] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[22] = sr & 0x7; sr >>= 3;
|
||||
xmc[23] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[24] = sr & 0x7; sr >>= 3;
|
||||
xmc[25] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4; /* 20 */
|
||||
Nc[2] = sr & 0x7f; sr >>= 7;
|
||||
bc[2] = sr & 0x3; sr >>= 2;
|
||||
Mc[2] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[2] = sr & 0x3f; sr >>= 6;
|
||||
|
||||
#undef xmc
|
||||
#define xmc (target + 46 - 26)
|
||||
|
||||
xmc[26] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[27] = sr & 0x7; sr >>= 3;
|
||||
xmc[28] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[29] = sr & 0x7; sr >>= 3;
|
||||
xmc[30] = sr & 0x7; sr >>= 3;
|
||||
xmc[31] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[32] = sr & 0x7; sr >>= 3;
|
||||
xmc[33] = sr & 0x7; sr >>= 3;
|
||||
xmc[34] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 25 */
|
||||
xmc[35] = sr & 0x7; sr >>= 3;
|
||||
xmc[36] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[37] = sr & 0x7; sr >>= 3;
|
||||
xmc[38] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[3] = sr & 0x7f; sr >>= 7;
|
||||
bc[3] = sr & 0x3; sr >>= 2;
|
||||
Mc[3] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[3] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (target + 63 - 39)
|
||||
|
||||
xmc[39] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[40] = sr & 0x7; sr >>= 3;
|
||||
xmc[41] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2; /* 30 */
|
||||
xmc[42] = sr & 0x7; sr >>= 3;
|
||||
xmc[43] = sr & 0x7; sr >>= 3;
|
||||
xmc[44] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[45] = sr & 0x7; sr >>= 3;
|
||||
xmc[46] = sr & 0x7; sr >>= 3;
|
||||
xmc[47] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[48] = sr & 0x7; sr >>= 3;
|
||||
xmc[49] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[50] = sr & 0x7; sr >>= 3;
|
||||
xmc[51] = sr & 0x7; sr >>= 3;
|
||||
|
||||
s->frame_chain = sr & 0xf;
|
||||
}
|
||||
else {
|
||||
sr = s->frame_chain;
|
||||
sr |= (uword)*c++ << 4; /* 1 */
|
||||
LARc[0] = sr & 0x3f; sr >>= 6;
|
||||
LARc[1] = sr & 0x3f; sr >>= 6;
|
||||
sr = *c++;
|
||||
LARc[2] = sr & 0x1f; sr >>= 5;
|
||||
sr |= (uword)*c++ << 3;
|
||||
LARc[3] = sr & 0x1f; sr >>= 5;
|
||||
LARc[4] = sr & 0xf; sr >>= 4;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[5] = sr & 0xf; sr >>= 4;
|
||||
LARc[6] = sr & 0x7; sr >>= 3;
|
||||
LARc[7] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 5 */
|
||||
Nc[0] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[0] = sr & 0x3; sr >>= 2;
|
||||
Mc[0] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[0] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (target + 12)
|
||||
xmc[0] = sr & 0x7; sr >>= 3;
|
||||
xmc[1] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[2] = sr & 0x7; sr >>= 3;
|
||||
xmc[3] = sr & 0x7; sr >>= 3;
|
||||
xmc[4] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[5] = sr & 0x7; sr >>= 3;
|
||||
xmc[6] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2; /* 10 */
|
||||
xmc[7] = sr & 0x7; sr >>= 3;
|
||||
xmc[8] = sr & 0x7; sr >>= 3;
|
||||
xmc[9] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[10] = sr & 0x7; sr >>= 3;
|
||||
xmc[11] = sr & 0x7; sr >>= 3;
|
||||
xmc[12] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[1] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[1] = sr & 0x3; sr >>= 2;
|
||||
Mc[1] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[1] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (target + 29 - 13)
|
||||
|
||||
xmc[13] = sr & 0x7; sr >>= 3;
|
||||
xmc[14] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 15 */
|
||||
xmc[15] = sr & 0x7; sr >>= 3;
|
||||
xmc[16] = sr & 0x7; sr >>= 3;
|
||||
xmc[17] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[18] = sr & 0x7; sr >>= 3;
|
||||
xmc[19] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[20] = sr & 0x7; sr >>= 3;
|
||||
xmc[21] = sr & 0x7; sr >>= 3;
|
||||
xmc[22] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[23] = sr & 0x7; sr >>= 3;
|
||||
xmc[24] = sr & 0x7; sr >>= 3;
|
||||
xmc[25] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[2] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1; /* 20 */
|
||||
bc[2] = sr & 0x3; sr >>= 2;
|
||||
Mc[2] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[2] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (target + 46 - 26)
|
||||
xmc[26] = sr & 0x7; sr >>= 3;
|
||||
xmc[27] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[28] = sr & 0x7; sr >>= 3;
|
||||
xmc[29] = sr & 0x7; sr >>= 3;
|
||||
xmc[30] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[31] = sr & 0x7; sr >>= 3;
|
||||
xmc[32] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[33] = sr & 0x7; sr >>= 3;
|
||||
xmc[34] = sr & 0x7; sr >>= 3;
|
||||
xmc[35] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 25 */
|
||||
xmc[36] = sr & 0x7; sr >>= 3;
|
||||
xmc[37] = sr & 0x7; sr >>= 3;
|
||||
xmc[38] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[3] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[3] = sr & 0x3; sr >>= 2;
|
||||
Mc[3] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[3] = sr & 0x3f; sr >>= 6;
|
||||
|
||||
#undef xmc
|
||||
#define xmc (target + 63 - 39)
|
||||
|
||||
xmc[39] = sr & 0x7; sr >>= 3;
|
||||
xmc[40] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[41] = sr & 0x7; sr >>= 3;
|
||||
xmc[42] = sr & 0x7; sr >>= 3;
|
||||
xmc[43] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 30 */
|
||||
xmc[44] = sr & 0x7; sr >>= 3;
|
||||
xmc[45] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[46] = sr & 0x7; sr >>= 3;
|
||||
xmc[47] = sr & 0x7; sr >>= 3;
|
||||
xmc[48] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[49] = sr & 0x7; sr >>= 3;
|
||||
xmc[50] = sr & 0x7; sr >>= 3;
|
||||
xmc[51] = sr & 0x7; sr >>= 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* GSM_MAGIC = (*c >> 4) & 0xF; */
|
||||
|
||||
if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1;
|
||||
|
||||
LARc[0] = (*c++ & 0xF) << 2; /* 1 */
|
||||
LARc[0] |= (*c >> 6) & 0x3;
|
||||
LARc[1] = *c++ & 0x3F;
|
||||
LARc[2] = (*c >> 3) & 0x1F;
|
||||
LARc[3] = (*c++ & 0x7) << 2;
|
||||
LARc[3] |= (*c >> 6) & 0x3;
|
||||
LARc[4] = (*c >> 2) & 0xF;
|
||||
LARc[5] = (*c++ & 0x3) << 2;
|
||||
LARc[5] |= (*c >> 6) & 0x3;
|
||||
LARc[6] = (*c >> 3) & 0x7;
|
||||
LARc[7] = *c++ & 0x7;
|
||||
|
||||
Nc[0] = (*c >> 1) & 0x7F;
|
||||
|
||||
bc[0] = (*c++ & 0x1) << 1;
|
||||
bc[0] |= (*c >> 7) & 0x1;
|
||||
|
||||
Mc[0] = (*c >> 5) & 0x3;
|
||||
|
||||
xmaxc[0] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[0] |= (*c >> 7) & 0x1;
|
||||
|
||||
#undef xmc
|
||||
#define xmc (target + 12)
|
||||
|
||||
xmc[0] = (*c >> 4) & 0x7;
|
||||
xmc[1] = (*c >> 1) & 0x7;
|
||||
xmc[2] = (*c++ & 0x1) << 2;
|
||||
xmc[2] |= (*c >> 6) & 0x3;
|
||||
xmc[3] = (*c >> 3) & 0x7;
|
||||
xmc[4] = *c++ & 0x7;
|
||||
xmc[5] = (*c >> 5) & 0x7;
|
||||
xmc[6] = (*c >> 2) & 0x7;
|
||||
xmc[7] = (*c++ & 0x3) << 1; /* 10 */
|
||||
xmc[7] |= (*c >> 7) & 0x1;
|
||||
xmc[8] = (*c >> 4) & 0x7;
|
||||
xmc[9] = (*c >> 1) & 0x7;
|
||||
xmc[10] = (*c++ & 0x1) << 2;
|
||||
xmc[10] |= (*c >> 6) & 0x3;
|
||||
xmc[11] = (*c >> 3) & 0x7;
|
||||
xmc[12] = *c++ & 0x7;
|
||||
|
||||
Nc[1] = (*c >> 1) & 0x7F;
|
||||
|
||||
bc[1] = (*c++ & 0x1) << 1;
|
||||
bc[1] |= (*c >> 7) & 0x1;
|
||||
|
||||
Mc[1] = (*c >> 5) & 0x3;
|
||||
|
||||
xmaxc[1] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[1] |= (*c >> 7) & 0x1;
|
||||
|
||||
#undef xmc
|
||||
#define xmc (target + 29 - 13)
|
||||
|
||||
xmc[13] = (*c >> 4) & 0x7;
|
||||
xmc[14] = (*c >> 1) & 0x7;
|
||||
xmc[15] = (*c++ & 0x1) << 2;
|
||||
xmc[15] |= (*c >> 6) & 0x3;
|
||||
xmc[16] = (*c >> 3) & 0x7;
|
||||
xmc[17] = *c++ & 0x7;
|
||||
xmc[18] = (*c >> 5) & 0x7;
|
||||
xmc[19] = (*c >> 2) & 0x7;
|
||||
xmc[20] = (*c++ & 0x3) << 1;
|
||||
xmc[20] |= (*c >> 7) & 0x1;
|
||||
xmc[21] = (*c >> 4) & 0x7;
|
||||
xmc[22] = (*c >> 1) & 0x7;
|
||||
xmc[23] = (*c++ & 0x1) << 2;
|
||||
xmc[23] |= (*c >> 6) & 0x3;
|
||||
xmc[24] = (*c >> 3) & 0x7;
|
||||
xmc[25] = *c++ & 0x7;
|
||||
|
||||
Nc[2] = (*c >> 1) & 0x7F;
|
||||
|
||||
bc[2] = (*c++ & 0x1) << 1; /* 20 */
|
||||
bc[2] |= (*c >> 7) & 0x1;
|
||||
|
||||
Mc[2] = (*c >> 5) & 0x3;
|
||||
|
||||
xmaxc[2] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[2] |= (*c >> 7) & 0x1;
|
||||
|
||||
#undef xmc
|
||||
#define xmc (target + 46 - 26)
|
||||
|
||||
xmc[26] = (*c >> 4) & 0x7;
|
||||
xmc[27] = (*c >> 1) & 0x7;
|
||||
xmc[28] = (*c++ & 0x1) << 2;
|
||||
xmc[28] |= (*c >> 6) & 0x3;
|
||||
xmc[29] = (*c >> 3) & 0x7;
|
||||
xmc[30] = *c++ & 0x7;
|
||||
xmc[31] = (*c >> 5) & 0x7;
|
||||
xmc[32] = (*c >> 2) & 0x7;
|
||||
xmc[33] = (*c++ & 0x3) << 1;
|
||||
xmc[33] |= (*c >> 7) & 0x1;
|
||||
xmc[34] = (*c >> 4) & 0x7;
|
||||
xmc[35] = (*c >> 1) & 0x7;
|
||||
xmc[36] = (*c++ & 0x1) << 2;
|
||||
xmc[36] |= (*c >> 6) & 0x3;
|
||||
xmc[37] = (*c >> 3) & 0x7;
|
||||
xmc[38] = *c++ & 0x7;
|
||||
|
||||
Nc[3] = (*c >> 1) & 0x7F;
|
||||
|
||||
bc[3] = (*c++ & 0x1) << 1;
|
||||
bc[3] |= (*c >> 7) & 0x1;
|
||||
|
||||
Mc[3] = (*c >> 5) & 0x3;
|
||||
|
||||
xmaxc[3] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[3] |= (*c >> 7) & 0x1;
|
||||
|
||||
#undef xmc
|
||||
#define xmc (target + 63 - 39)
|
||||
|
||||
xmc[39] = (*c >> 4) & 0x7;
|
||||
xmc[40] = (*c >> 1) & 0x7;
|
||||
xmc[41] = (*c++ & 0x1) << 2;
|
||||
xmc[41] |= (*c >> 6) & 0x3;
|
||||
xmc[42] = (*c >> 3) & 0x7;
|
||||
xmc[43] = *c++ & 0x7; /* 30 */
|
||||
xmc[44] = (*c >> 5) & 0x7;
|
||||
xmc[45] = (*c >> 2) & 0x7;
|
||||
xmc[46] = (*c++ & 0x3) << 1;
|
||||
xmc[46] |= (*c >> 7) & 0x1;
|
||||
xmc[47] = (*c >> 4) & 0x7;
|
||||
xmc[48] = (*c >> 1) & 0x7;
|
||||
xmc[49] = (*c++ & 0x1) << 2;
|
||||
xmc[49] |= (*c >> 6) & 0x3;
|
||||
xmc[50] = (*c >> 3) & 0x7;
|
||||
xmc[51] = *c & 0x7; /* 33 */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+515
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
void gsm_implode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c)
|
||||
{
|
||||
/* variable size index
|
||||
|
||||
GSM_MAGIC 4 -
|
||||
|
||||
LARc[0] 6 0
|
||||
LARc[1] 6 1
|
||||
LARc[2] 5 2
|
||||
LARc[3] 5 3
|
||||
LARc[4] 4 4
|
||||
LARc[5] 4 5
|
||||
LARc[6] 3 6
|
||||
LARc[7] 3 7
|
||||
|
||||
Nc[0] 7 8
|
||||
bc[0] 2 9
|
||||
Mc[0] 2 10
|
||||
xmaxc[0] 6 11
|
||||
xmc[0] 3 12
|
||||
xmc[1] 3 13
|
||||
xmc[2] 3 14
|
||||
xmc[3] 3 15
|
||||
xmc[4] 3 16
|
||||
xmc[5] 3 17
|
||||
xmc[6] 3 18
|
||||
xmc[7] 3 19
|
||||
xmc[8] 3 20
|
||||
xmc[9] 3 21
|
||||
xmc[10] 3 22
|
||||
xmc[11] 3 23
|
||||
xmc[12] 3 24
|
||||
|
||||
Nc[1] 7 25
|
||||
bc[1] 2 26
|
||||
Mc[1] 2 27
|
||||
xmaxc[1] 6 28
|
||||
xmc[13] 3 29
|
||||
xmc[14] 3 30
|
||||
xmc[15] 3 31
|
||||
xmc[16] 3 32
|
||||
xmc[17] 3 33
|
||||
xmc[18] 3 34
|
||||
xmc[19] 3 35
|
||||
xmc[20] 3 36
|
||||
xmc[21] 3 37
|
||||
xmc[22] 3 38
|
||||
xmc[23] 3 39
|
||||
xmc[24] 3 40
|
||||
xmc[25] 3 41
|
||||
|
||||
Nc[2] 7 42
|
||||
bc[2] 2 43
|
||||
Mc[2] 2 44
|
||||
xmaxc[2] 6 45
|
||||
xmc[26] 3 46
|
||||
xmc[27] 3 47
|
||||
xmc[28] 3 48
|
||||
xmc[29] 3 49
|
||||
xmc[30] 3 50
|
||||
xmc[31] 3 51
|
||||
xmc[32] 3 52
|
||||
xmc[33] 3 53
|
||||
xmc[34] 3 54
|
||||
xmc[35] 3 55
|
||||
xmc[36] 3 56
|
||||
xmc[37] 3 57
|
||||
xmc[38] 3 58
|
||||
|
||||
Nc[3] 7 59
|
||||
bc[3] 2 60
|
||||
Mc[3] 2 61
|
||||
xmaxc[3] 6 62
|
||||
xmc[39] 3 63
|
||||
xmc[40] 3 64
|
||||
xmc[41] 3 65
|
||||
xmc[42] 3 66
|
||||
xmc[43] 3 67
|
||||
xmc[44] 3 68
|
||||
xmc[45] 3 69
|
||||
xmc[46] 3 70
|
||||
xmc[47] 3 71
|
||||
xmc[48] 3 72
|
||||
xmc[49] 3 73
|
||||
xmc[50] 3 74
|
||||
xmc[51] 3 75
|
||||
*/
|
||||
|
||||
/* There are 76 parameters per frame. The first eight are
|
||||
* unique. The remaining 68 are four identical subframes of
|
||||
* 17 parameters each. gsm_implode converts from a representation
|
||||
* of these parameters as values in one array of signed words
|
||||
* to the "packed" version of a GSM frame.
|
||||
*/
|
||||
|
||||
# define LARc source
|
||||
# define Nc *((gsm_signal (*) [17])(source + 8))
|
||||
# define bc *((gsm_signal (*) [17])(source + 9))
|
||||
# define Mc *((gsm_signal (*) [17])(source + 10))
|
||||
# define xmaxc *((gsm_signal (*) [17])(source + 11))
|
||||
|
||||
#ifdef WAV49
|
||||
if (s->wav_fmt) {
|
||||
|
||||
uword sr = 0;
|
||||
if (s->frame_index == 0) {
|
||||
|
||||
sr = *c++;
|
||||
LARc[0] = sr & 0x3f; sr >>= 6;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[1] = sr & 0x3f; sr >>= 6;
|
||||
sr |= (uword)*c++ << 4;
|
||||
LARc[2] = sr & 0x1f; sr >>= 5;
|
||||
LARc[3] = sr & 0x1f; sr >>= 5;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[4] = sr & 0xf; sr >>= 4;
|
||||
LARc[5] = sr & 0xf; sr >>= 4;
|
||||
sr |= (uword)*c++ << 2; /* 5 */
|
||||
LARc[6] = sr & 0x7; sr >>= 3;
|
||||
LARc[7] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[0] = sr & 0x7f; sr >>= 7;
|
||||
bc[0] = sr & 0x3; sr >>= 2;
|
||||
Mc[0] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[0] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (source + 12)
|
||||
xmc[0] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[1] = sr & 0x7; sr >>= 3;
|
||||
xmc[2] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[3] = sr & 0x7; sr >>= 3;
|
||||
xmc[4] = sr & 0x7; sr >>= 3;
|
||||
xmc[5] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 10 */
|
||||
xmc[6] = sr & 0x7; sr >>= 3;
|
||||
xmc[7] = sr & 0x7; sr >>= 3;
|
||||
xmc[8] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[9] = sr & 0x7; sr >>= 3;
|
||||
xmc[10] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[11] = sr & 0x7; sr >>= 3;
|
||||
xmc[12] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[1] = sr & 0x7f; sr >>= 7;
|
||||
bc[1] = sr & 0x3; sr >>= 2;
|
||||
Mc[1] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[1] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (source + 29 - 13)
|
||||
xmc[13] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 15 */
|
||||
xmc[14] = sr & 0x7; sr >>= 3;
|
||||
xmc[15] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[16] = sr & 0x7; sr >>= 3;
|
||||
xmc[17] = sr & 0x7; sr >>= 3;
|
||||
xmc[18] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[19] = sr & 0x7; sr >>= 3;
|
||||
xmc[20] = sr & 0x7; sr >>= 3;
|
||||
xmc[21] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[22] = sr & 0x7; sr >>= 3;
|
||||
xmc[23] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[24] = sr & 0x7; sr >>= 3;
|
||||
xmc[25] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4; /* 20 */
|
||||
Nc[2] = sr & 0x7f; sr >>= 7;
|
||||
bc[2] = sr & 0x3; sr >>= 2;
|
||||
Mc[2] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[2] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (source + 46 - 26)
|
||||
xmc[26] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[27] = sr & 0x7; sr >>= 3;
|
||||
xmc[28] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[29] = sr & 0x7; sr >>= 3;
|
||||
xmc[30] = sr & 0x7; sr >>= 3;
|
||||
xmc[31] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[32] = sr & 0x7; sr >>= 3;
|
||||
xmc[33] = sr & 0x7; sr >>= 3;
|
||||
xmc[34] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 25 */
|
||||
xmc[35] = sr & 0x7; sr >>= 3;
|
||||
xmc[36] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[37] = sr & 0x7; sr >>= 3;
|
||||
xmc[38] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[3] = sr & 0x7f; sr >>= 7;
|
||||
bc[3] = sr & 0x3; sr >>= 2;
|
||||
Mc[3] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[3] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (source + 63 - 39)
|
||||
|
||||
xmc[39] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[40] = sr & 0x7; sr >>= 3;
|
||||
xmc[41] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2; /* 30 */
|
||||
xmc[42] = sr & 0x7; sr >>= 3;
|
||||
xmc[43] = sr & 0x7; sr >>= 3;
|
||||
xmc[44] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[45] = sr & 0x7; sr >>= 3;
|
||||
xmc[46] = sr & 0x7; sr >>= 3;
|
||||
xmc[47] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[48] = sr & 0x7; sr >>= 3;
|
||||
xmc[49] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[50] = sr & 0x7; sr >>= 3;
|
||||
xmc[51] = sr & 0x7; sr >>= 3;
|
||||
|
||||
s->frame_chain = sr & 0xf;
|
||||
}
|
||||
else {
|
||||
sr = s->frame_chain;
|
||||
sr |= (uword)*c++ << 4; /* 1 */
|
||||
LARc[0] = sr & 0x3f; sr >>= 6;
|
||||
LARc[1] = sr & 0x3f; sr >>= 6;
|
||||
sr = *c++;
|
||||
LARc[2] = sr & 0x1f; sr >>= 5;
|
||||
sr |= (uword)*c++ << 3;
|
||||
LARc[3] = sr & 0x1f; sr >>= 5;
|
||||
LARc[4] = sr & 0xf; sr >>= 4;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[5] = sr & 0xf; sr >>= 4;
|
||||
LARc[6] = sr & 0x7; sr >>= 3;
|
||||
LARc[7] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 5 */
|
||||
Nc[0] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[0] = sr & 0x3; sr >>= 2;
|
||||
Mc[0] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[0] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (source + 12)
|
||||
xmc[0] = sr & 0x7; sr >>= 3;
|
||||
xmc[1] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[2] = sr & 0x7; sr >>= 3;
|
||||
xmc[3] = sr & 0x7; sr >>= 3;
|
||||
xmc[4] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[5] = sr & 0x7; sr >>= 3;
|
||||
xmc[6] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2; /* 10 */
|
||||
xmc[7] = sr & 0x7; sr >>= 3;
|
||||
xmc[8] = sr & 0x7; sr >>= 3;
|
||||
xmc[9] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[10] = sr & 0x7; sr >>= 3;
|
||||
xmc[11] = sr & 0x7; sr >>= 3;
|
||||
xmc[12] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[1] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[1] = sr & 0x3; sr >>= 2;
|
||||
Mc[1] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[1] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (source + 29 - 13)
|
||||
xmc[13] = sr & 0x7; sr >>= 3;
|
||||
xmc[14] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 15 */
|
||||
xmc[15] = sr & 0x7; sr >>= 3;
|
||||
xmc[16] = sr & 0x7; sr >>= 3;
|
||||
xmc[17] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[18] = sr & 0x7; sr >>= 3;
|
||||
xmc[19] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[20] = sr & 0x7; sr >>= 3;
|
||||
xmc[21] = sr & 0x7; sr >>= 3;
|
||||
xmc[22] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[23] = sr & 0x7; sr >>= 3;
|
||||
xmc[24] = sr & 0x7; sr >>= 3;
|
||||
xmc[25] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[2] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1; /* 20 */
|
||||
bc[2] = sr & 0x3; sr >>= 2;
|
||||
Mc[2] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[2] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (source + 46 - 26)
|
||||
xmc[26] = sr & 0x7; sr >>= 3;
|
||||
xmc[27] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[28] = sr & 0x7; sr >>= 3;
|
||||
xmc[29] = sr & 0x7; sr >>= 3;
|
||||
xmc[30] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[31] = sr & 0x7; sr >>= 3;
|
||||
xmc[32] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[33] = sr & 0x7; sr >>= 3;
|
||||
xmc[34] = sr & 0x7; sr >>= 3;
|
||||
xmc[35] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 25 */
|
||||
xmc[36] = sr & 0x7; sr >>= 3;
|
||||
xmc[37] = sr & 0x7; sr >>= 3;
|
||||
xmc[38] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[3] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[3] = sr & 0x3; sr >>= 2;
|
||||
Mc[3] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[3] = sr & 0x3f; sr >>= 6;
|
||||
#undef xmc
|
||||
#define xmc (source + 63 - 39)
|
||||
|
||||
xmc[39] = sr & 0x7; sr >>= 3;
|
||||
xmc[40] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[41] = sr & 0x7; sr >>= 3;
|
||||
xmc[42] = sr & 0x7; sr >>= 3;
|
||||
xmc[43] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 30 */
|
||||
xmc[44] = sr & 0x7; sr >>= 3;
|
||||
xmc[45] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[46] = sr & 0x7; sr >>= 3;
|
||||
xmc[47] = sr & 0x7; sr >>= 3;
|
||||
xmc[48] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[49] = sr & 0x7; sr >>= 3;
|
||||
xmc[50] = sr & 0x7; sr >>= 3;
|
||||
xmc[51] = sr & 0x7; sr >>= 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
*c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */
|
||||
| ((LARc[0] >> 2) & 0xF);
|
||||
*c++ = ((LARc[0] & 0x3) << 6)
|
||||
| (LARc[1] & 0x3F);
|
||||
*c++ = ((LARc[2] & 0x1F) << 3)
|
||||
| ((LARc[3] >> 2) & 0x7);
|
||||
*c++ = ((LARc[3] & 0x3) << 6)
|
||||
| ((LARc[4] & 0xF) << 2)
|
||||
| ((LARc[5] >> 2) & 0x3);
|
||||
*c++ = ((LARc[5] & 0x3) << 6)
|
||||
| ((LARc[6] & 0x7) << 3)
|
||||
| (LARc[7] & 0x7);
|
||||
|
||||
|
||||
*c++ = ((Nc[0] & 0x7F) << 1)
|
||||
|
||||
|
||||
| ((bc[0] >> 1) & 0x1);
|
||||
*c++ = ((bc[0] & 0x1) << 7)
|
||||
|
||||
|
||||
| ((Mc[0] & 0x3) << 5)
|
||||
|
||||
| ((xmaxc[0] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[0] & 0x1) << 7)
|
||||
|
||||
#undef xmc
|
||||
#define xmc (source + 12)
|
||||
|
||||
| ((xmc[0] & 0x7) << 4)
|
||||
| ((xmc[1] & 0x7) << 1)
|
||||
| ((xmc[2] >> 2) & 0x1);
|
||||
*c++ = ((xmc[2] & 0x3) << 6)
|
||||
| ((xmc[3] & 0x7) << 3)
|
||||
| (xmc[4] & 0x7);
|
||||
*c++ = ((xmc[5] & 0x7) << 5) /* 10 */
|
||||
| ((xmc[6] & 0x7) << 2)
|
||||
| ((xmc[7] >> 1) & 0x3);
|
||||
*c++ = ((xmc[7] & 0x1) << 7)
|
||||
| ((xmc[8] & 0x7) << 4)
|
||||
| ((xmc[9] & 0x7) << 1)
|
||||
| ((xmc[10] >> 2) & 0x1);
|
||||
*c++ = ((xmc[10] & 0x3) << 6)
|
||||
| ((xmc[11] & 0x7) << 3)
|
||||
| (xmc[12] & 0x7);
|
||||
|
||||
|
||||
*c++ = ((Nc[1] & 0x7F) << 1)
|
||||
|
||||
|
||||
| ((bc[1] >> 1) & 0x1);
|
||||
*c++ = ((bc[1] & 0x1) << 7)
|
||||
|
||||
|
||||
| ((Mc[1] & 0x3) << 5)
|
||||
|
||||
|
||||
| ((xmaxc[1] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[1] & 0x1) << 7)
|
||||
|
||||
#undef xmc
|
||||
#define xmc (source + 29 - 13)
|
||||
|
||||
| ((xmc[13] & 0x7) << 4)
|
||||
| ((xmc[14] & 0x7) << 1)
|
||||
| ((xmc[15] >> 2) & 0x1);
|
||||
*c++ = ((xmc[15] & 0x3) << 6)
|
||||
| ((xmc[16] & 0x7) << 3)
|
||||
| (xmc[17] & 0x7);
|
||||
*c++ = ((xmc[18] & 0x7) << 5)
|
||||
| ((xmc[19] & 0x7) << 2)
|
||||
| ((xmc[20] >> 1) & 0x3);
|
||||
*c++ = ((xmc[20] & 0x1) << 7)
|
||||
| ((xmc[21] & 0x7) << 4)
|
||||
| ((xmc[22] & 0x7) << 1)
|
||||
| ((xmc[23] >> 2) & 0x1);
|
||||
*c++ = ((xmc[23] & 0x3) << 6)
|
||||
| ((xmc[24] & 0x7) << 3)
|
||||
| (xmc[25] & 0x7);
|
||||
|
||||
|
||||
*c++ = ((Nc[2] & 0x7F) << 1) /* 20 */
|
||||
|
||||
|
||||
| ((bc[2] >> 1) & 0x1);
|
||||
*c++ = ((bc[2] & 0x1) << 7)
|
||||
|
||||
|
||||
| ((Mc[2] & 0x3) << 5)
|
||||
|
||||
|
||||
| ((xmaxc[2] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[2] & 0x1) << 7)
|
||||
|
||||
#undef xmc
|
||||
#define xmc (source + 46 - 26)
|
||||
|
||||
| ((xmc[26] & 0x7) << 4)
|
||||
| ((xmc[27] & 0x7) << 1)
|
||||
| ((xmc[28] >> 2) & 0x1);
|
||||
*c++ = ((xmc[28] & 0x3) << 6)
|
||||
| ((xmc[29] & 0x7) << 3)
|
||||
| (xmc[30] & 0x7);
|
||||
*c++ = ((xmc[31] & 0x7) << 5)
|
||||
| ((xmc[32] & 0x7) << 2)
|
||||
| ((xmc[33] >> 1) & 0x3);
|
||||
*c++ = ((xmc[33] & 0x1) << 7)
|
||||
| ((xmc[34] & 0x7) << 4)
|
||||
| ((xmc[35] & 0x7) << 1)
|
||||
| ((xmc[36] >> 2) & 0x1);
|
||||
*c++ = ((xmc[36] & 0x3) << 6)
|
||||
| ((xmc[37] & 0x7) << 3)
|
||||
| (xmc[38] & 0x7);
|
||||
|
||||
|
||||
*c++ = ((Nc[3] & 0x7F) << 1)
|
||||
|
||||
|
||||
| ((bc[3] >> 1) & 0x1);
|
||||
*c++ = ((bc[3] & 0x1) << 7)
|
||||
|
||||
|
||||
| ((Mc[3] & 0x3) << 5)
|
||||
|
||||
|
||||
| ((xmaxc[3] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[3] & 0x1) << 7)
|
||||
|
||||
#undef xmc
|
||||
#define xmc (source + 63 - 39)
|
||||
|
||||
| ((xmc[39] & 0x7) << 4)
|
||||
| ((xmc[40] & 0x7) << 1)
|
||||
| ((xmc[41] >> 2) & 0x1);
|
||||
*c++ = ((xmc[41] & 0x3) << 6) /* 30 */
|
||||
| ((xmc[42] & 0x7) << 3)
|
||||
| (xmc[43] & 0x7);
|
||||
*c++ = ((xmc[44] & 0x7) << 5)
|
||||
| ((xmc[45] & 0x7) << 2)
|
||||
| ((xmc[46] >> 1) & 0x3);
|
||||
*c++ = ((xmc[46] & 0x1) << 7)
|
||||
| ((xmc[47] & 0x7) << 4)
|
||||
| ((xmc[48] & 0x7) << 1)
|
||||
| ((xmc[49] >> 2) & 0x1);
|
||||
*c++ = ((xmc[49] & 0x3) << 6)
|
||||
| ((xmc[50] & 0x7) << 3)
|
||||
| (xmc[51] & 0x7);
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
int gsm_option P3((r, opt, val), gsm r, int opt, int * val)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
switch (opt) {
|
||||
case GSM_OPT_LTP_CUT:
|
||||
#ifdef LTP_CUT
|
||||
result = r->ltp_cut;
|
||||
if (val) r->ltp_cut = *val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_VERBOSE:
|
||||
#ifndef NDEBUG
|
||||
result = r->verbose;
|
||||
if (val) r->verbose = *val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_FAST:
|
||||
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
result = r->fast;
|
||||
if (val) r->fast = !!*val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_FRAME_CHAIN:
|
||||
|
||||
#ifdef WAV49
|
||||
result = r->frame_chain;
|
||||
if (val) r->frame_chain = *val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_FRAME_INDEX:
|
||||
|
||||
#ifdef WAV49
|
||||
result = r->frame_index;
|
||||
if (val) r->frame_index = *val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_WAV49:
|
||||
|
||||
#ifdef WAV49
|
||||
result = r->wav_fmt;
|
||||
if (val) r->wav_fmt = !!*val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
int gsm_print P3((f, s, c), FILE * f, gsm s, gsm_byte * c)
|
||||
{
|
||||
word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4];
|
||||
|
||||
/* GSM_MAGIC = (*c >> 4) & 0xF; */
|
||||
|
||||
if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1;
|
||||
|
||||
LARc[0] = (*c++ & 0xF) << 2; /* 1 */
|
||||
LARc[0] |= (*c >> 6) & 0x3;
|
||||
LARc[1] = *c++ & 0x3F;
|
||||
LARc[2] = (*c >> 3) & 0x1F;
|
||||
LARc[3] = (*c++ & 0x7) << 2;
|
||||
LARc[3] |= (*c >> 6) & 0x3;
|
||||
LARc[4] = (*c >> 2) & 0xF;
|
||||
LARc[5] = (*c++ & 0x3) << 2;
|
||||
LARc[5] |= (*c >> 6) & 0x3;
|
||||
LARc[6] = (*c >> 3) & 0x7;
|
||||
LARc[7] = *c++ & 0x7;
|
||||
|
||||
|
||||
Nc[0] = (*c >> 1) & 0x7F;
|
||||
bc[0] = (*c++ & 0x1) << 1;
|
||||
bc[0] |= (*c >> 7) & 0x1;
|
||||
Mc[0] = (*c >> 5) & 0x3;
|
||||
xmaxc[0] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[0] |= (*c >> 7) & 0x1;
|
||||
xmc[0] = (*c >> 4) & 0x7;
|
||||
xmc[1] = (*c >> 1) & 0x7;
|
||||
xmc[2] = (*c++ & 0x1) << 2;
|
||||
xmc[2] |= (*c >> 6) & 0x3;
|
||||
xmc[3] = (*c >> 3) & 0x7;
|
||||
xmc[4] = *c++ & 0x7;
|
||||
xmc[5] = (*c >> 5) & 0x7;
|
||||
xmc[6] = (*c >> 2) & 0x7;
|
||||
xmc[7] = (*c++ & 0x3) << 1; /* 10 */
|
||||
xmc[7] |= (*c >> 7) & 0x1;
|
||||
xmc[8] = (*c >> 4) & 0x7;
|
||||
xmc[9] = (*c >> 1) & 0x7;
|
||||
xmc[10] = (*c++ & 0x1) << 2;
|
||||
xmc[10] |= (*c >> 6) & 0x3;
|
||||
xmc[11] = (*c >> 3) & 0x7;
|
||||
xmc[12] = *c++ & 0x7;
|
||||
|
||||
Nc[1] = (*c >> 1) & 0x7F;
|
||||
bc[1] = (*c++ & 0x1) << 1;
|
||||
bc[1] |= (*c >> 7) & 0x1;
|
||||
Mc[1] = (*c >> 5) & 0x3;
|
||||
xmaxc[1] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[1] |= (*c >> 7) & 0x1;
|
||||
xmc[13] = (*c >> 4) & 0x7;
|
||||
xmc[14] = (*c >> 1) & 0x7;
|
||||
xmc[15] = (*c++ & 0x1) << 2;
|
||||
xmc[15] |= (*c >> 6) & 0x3;
|
||||
xmc[16] = (*c >> 3) & 0x7;
|
||||
xmc[17] = *c++ & 0x7;
|
||||
xmc[18] = (*c >> 5) & 0x7;
|
||||
xmc[19] = (*c >> 2) & 0x7;
|
||||
xmc[20] = (*c++ & 0x3) << 1;
|
||||
xmc[20] |= (*c >> 7) & 0x1;
|
||||
xmc[21] = (*c >> 4) & 0x7;
|
||||
xmc[22] = (*c >> 1) & 0x7;
|
||||
xmc[23] = (*c++ & 0x1) << 2;
|
||||
xmc[23] |= (*c >> 6) & 0x3;
|
||||
xmc[24] = (*c >> 3) & 0x7;
|
||||
xmc[25] = *c++ & 0x7;
|
||||
|
||||
|
||||
Nc[2] = (*c >> 1) & 0x7F;
|
||||
bc[2] = (*c++ & 0x1) << 1; /* 20 */
|
||||
bc[2] |= (*c >> 7) & 0x1;
|
||||
Mc[2] = (*c >> 5) & 0x3;
|
||||
xmaxc[2] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[2] |= (*c >> 7) & 0x1;
|
||||
xmc[26] = (*c >> 4) & 0x7;
|
||||
xmc[27] = (*c >> 1) & 0x7;
|
||||
xmc[28] = (*c++ & 0x1) << 2;
|
||||
xmc[28] |= (*c >> 6) & 0x3;
|
||||
xmc[29] = (*c >> 3) & 0x7;
|
||||
xmc[30] = *c++ & 0x7;
|
||||
xmc[31] = (*c >> 5) & 0x7;
|
||||
xmc[32] = (*c >> 2) & 0x7;
|
||||
xmc[33] = (*c++ & 0x3) << 1;
|
||||
xmc[33] |= (*c >> 7) & 0x1;
|
||||
xmc[34] = (*c >> 4) & 0x7;
|
||||
xmc[35] = (*c >> 1) & 0x7;
|
||||
xmc[36] = (*c++ & 0x1) << 2;
|
||||
xmc[36] |= (*c >> 6) & 0x3;
|
||||
xmc[37] = (*c >> 3) & 0x7;
|
||||
xmc[38] = *c++ & 0x7;
|
||||
|
||||
Nc[3] = (*c >> 1) & 0x7F;
|
||||
bc[3] = (*c++ & 0x1) << 1;
|
||||
bc[3] |= (*c >> 7) & 0x1;
|
||||
Mc[3] = (*c >> 5) & 0x3;
|
||||
xmaxc[3] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[3] |= (*c >> 7) & 0x1;
|
||||
|
||||
xmc[39] = (*c >> 4) & 0x7;
|
||||
xmc[40] = (*c >> 1) & 0x7;
|
||||
xmc[41] = (*c++ & 0x1) << 2;
|
||||
xmc[41] |= (*c >> 6) & 0x3;
|
||||
xmc[42] = (*c >> 3) & 0x7;
|
||||
xmc[43] = *c++ & 0x7; /* 30 */
|
||||
xmc[44] = (*c >> 5) & 0x7;
|
||||
xmc[45] = (*c >> 2) & 0x7;
|
||||
xmc[46] = (*c++ & 0x3) << 1;
|
||||
xmc[46] |= (*c >> 7) & 0x1;
|
||||
xmc[47] = (*c >> 4) & 0x7;
|
||||
xmc[48] = (*c >> 1) & 0x7;
|
||||
xmc[49] = (*c++ & 0x1) << 2;
|
||||
xmc[49] |= (*c >> 6) & 0x3;
|
||||
xmc[50] = (*c >> 3) & 0x7;
|
||||
xmc[51] = *c & 0x7; /* 33 */
|
||||
|
||||
fprintf(f,
|
||||
"LARc:\t%2.2d %2.2d %2.2d %2.2d %2.2d %2.2d %2.2d %2.2d\n",
|
||||
LARc[0],LARc[1],LARc[2],LARc[3],LARc[4],LARc[5],LARc[6],LARc[7]);
|
||||
|
||||
fprintf(f, "#1: Nc %4.4d bc %d Mc %d xmaxc %d\n",
|
||||
Nc[0], bc[0], Mc[0], xmaxc[0]);
|
||||
fprintf(f,
|
||||
"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n",
|
||||
xmc[0],xmc[1],xmc[2],xmc[3],xmc[4],xmc[5],xmc[6],
|
||||
xmc[7],xmc[8],xmc[9],xmc[10],xmc[11],xmc[12] );
|
||||
|
||||
fprintf(f, "#2: Nc %4.4d bc %d Mc %d xmaxc %d\n",
|
||||
Nc[1], bc[1], Mc[1], xmaxc[1]);
|
||||
fprintf(f,
|
||||
"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n",
|
||||
xmc[13+0],xmc[13+1],xmc[13+2],xmc[13+3],xmc[13+4],xmc[13+5],
|
||||
xmc[13+6], xmc[13+7],xmc[13+8],xmc[13+9],xmc[13+10],xmc[13+11],
|
||||
xmc[13+12] );
|
||||
|
||||
fprintf(f, "#3: Nc %4.4d bc %d Mc %d xmaxc %d\n",
|
||||
Nc[2], bc[2], Mc[2], xmaxc[2]);
|
||||
fprintf(f,
|
||||
"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n",
|
||||
xmc[26+0],xmc[26+1],xmc[26+2],xmc[26+3],xmc[26+4],xmc[26+5],
|
||||
xmc[26+6], xmc[26+7],xmc[26+8],xmc[26+9],xmc[26+10],xmc[26+11],
|
||||
xmc[26+12] );
|
||||
|
||||
fprintf(f, "#4: Nc %4.4d bc %d Mc %d xmaxc %d\n",
|
||||
Nc[3], bc[3], Mc[3], xmaxc[3]);
|
||||
fprintf(f,
|
||||
"\t%.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d %.2d\n",
|
||||
xmc[39+0],xmc[39+1],xmc[39+2],xmc[39+3],xmc[39+4],xmc[39+5],
|
||||
xmc[39+6], xmc[39+7],xmc[39+8],xmc[39+9],xmc[39+10],xmc[39+11],
|
||||
xmc[39+12] );
|
||||
|
||||
return 0;
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/* k6opt.h vector functions optimized for MMX extensions to x86
|
||||
*
|
||||
* Copyright (C) 1999 by Stanley J. Brooks <stabro@megsinet.net>
|
||||
*
|
||||
* Any use of this software is permitted provided that this notice is not
|
||||
* removed and that neither the authors nor the Technische Universitaet Berlin
|
||||
* are deemed to have made any representations as to the suitability of this
|
||||
* software for any purpose nor are held responsible for any defects of
|
||||
* this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE;
|
||||
* not even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Chicago, 03.12.1999
|
||||
* Stanley J. Brooks
|
||||
*/
|
||||
|
||||
extern void Weighting_filter P2((e, x),
|
||||
const word * e, /* signal [-5..0.39.44] IN */
|
||||
word * x /* signal [0..39] OUT */
|
||||
)
|
||||
;
|
||||
|
||||
extern longword k6maxcc P3((wt,dp,Nc_out),
|
||||
const word *wt,
|
||||
const word *dp,
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
;
|
||||
/*
|
||||
* k6maxmin(p,n,out[])
|
||||
* input p[n] is array of shorts (require n>0)
|
||||
* returns (long) maximum absolute value..
|
||||
* if out!=NULL, also returns out[0] the maximum and out[1] the minimum
|
||||
*/
|
||||
extern longword k6maxmin P3((p,n,out),
|
||||
const word *p,
|
||||
int n,
|
||||
word *out /* out[0] is max, out[1] is min */
|
||||
)
|
||||
;
|
||||
|
||||
extern longword k6iprod P3((p,q,n),
|
||||
const word *p,
|
||||
const word *q,
|
||||
int n
|
||||
)
|
||||
;
|
||||
|
||||
/*
|
||||
* k6vsraw(p,n,bits)
|
||||
* input p[n] is array of shorts (require n>0)
|
||||
* shift/round each to the right by bits>=0 bits.
|
||||
*/
|
||||
extern void k6vsraw P3((p,n,bits),
|
||||
const word *p,
|
||||
int n,
|
||||
int bits
|
||||
)
|
||||
;
|
||||
|
||||
/*
|
||||
* k6vsllw(p,n,bits)
|
||||
* input p[n] is array of shorts (require n>0)
|
||||
* shift each to the left by bits>=0 bits.
|
||||
*/
|
||||
extern void k6vsllw P3((p,n,bits),
|
||||
const word *p,
|
||||
int n,
|
||||
int bits
|
||||
)
|
||||
;
|
||||
|
||||
#if 1 /* there isn't any significant speed gain from mmx here: */
|
||||
extern void Short_term_analysis_filteringx P4((u0,rp0,k_n,s),
|
||||
register word * u0,
|
||||
register word * rp0, /* [0..7] IN */
|
||||
register int k_n, /* k_end - k_start */
|
||||
register word * s /* [0..n-1] IN/OUT */
|
||||
)
|
||||
;
|
||||
/*
|
||||
#define Short_term_analysis_filtering Short_term_analysis_filteringx
|
||||
*/
|
||||
#endif
|
||||
+755
@@ -0,0 +1,755 @@
|
||||
/* k6opt.s vector functions optimized for MMX extensions to x86
|
||||
*
|
||||
* Copyright (C) 1999 by Stanley J. Brooks <stabro@megsinet.net>
|
||||
*
|
||||
* Any use of this software is permitted provided that this notice is not
|
||||
* removed and that neither the authors nor the Technische Universitaet Berlin
|
||||
* are deemed to have made any representations as to the suitability of this
|
||||
* software for any purpose nor are held responsible for any defects of
|
||||
* this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE;
|
||||
* not even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Chicago, 03.12.1999
|
||||
* Stanley J. Brooks
|
||||
*/
|
||||
|
||||
.file "k6opt.s"
|
||||
.version "01.01"
|
||||
/* gcc2_compiled.: */
|
||||
.section .rodata
|
||||
.align 4
|
||||
.type coefs,@object
|
||||
.size coefs,24
|
||||
coefs:
|
||||
.value -134
|
||||
.value -374
|
||||
.value 0
|
||||
.value 2054
|
||||
.value 5741
|
||||
.value 8192
|
||||
.value 5741
|
||||
.value 2054
|
||||
.value 0
|
||||
.value -374
|
||||
.value -134
|
||||
.value 0
|
||||
.text
|
||||
.align 4
|
||||
/* void Weighting_filter (const short *e, short *x) */
|
||||
.globl Weighting_filter
|
||||
.type Weighting_filter,@function
|
||||
Weighting_filter:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
movl 12(%ebp),%edi
|
||||
movl 8(%ebp),%ebx
|
||||
addl $-10,%ebx
|
||||
emms
|
||||
movl $0x1000,%eax; movd %eax,%mm5 /* for rounding */
|
||||
movq coefs,%mm1
|
||||
movq coefs+8,%mm2
|
||||
movq coefs+16,%mm3
|
||||
xorl %esi,%esi
|
||||
.p2align 2
|
||||
.L21:
|
||||
movq (%ebx,%esi,2),%mm0
|
||||
pmaddwd %mm1,%mm0
|
||||
|
||||
movq 8(%ebx,%esi,2),%mm4
|
||||
pmaddwd %mm2,%mm4
|
||||
paddd %mm4,%mm0
|
||||
|
||||
movq 16(%ebx,%esi,2),%mm4
|
||||
pmaddwd %mm3,%mm4
|
||||
paddd %mm4,%mm0
|
||||
|
||||
movq %mm0,%mm4
|
||||
punpckhdq %mm0,%mm4 /* mm4 has high int32 of mm0 dup'd */
|
||||
paddd %mm4,%mm0;
|
||||
|
||||
paddd %mm5,%mm0 /* add for roundoff */
|
||||
psrad $13,%mm0
|
||||
packssdw %mm0,%mm0
|
||||
movd %mm0,%eax /* ax has result */
|
||||
movw %ax,(%edi,%esi,2)
|
||||
incl %esi
|
||||
cmpl $39,%esi
|
||||
jle .L21
|
||||
emms
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe1:
|
||||
.size Weighting_filter,.Lfe1-Weighting_filter
|
||||
|
||||
.macro ccstep n
|
||||
.if \n
|
||||
movq \n(%edi),%mm1
|
||||
movq \n(%esi),%mm2
|
||||
.else
|
||||
movq (%edi),%mm1
|
||||
movq (%esi),%mm2
|
||||
.endif
|
||||
pmaddwd %mm2,%mm1
|
||||
paddd %mm1,%mm0
|
||||
.endm
|
||||
|
||||
.align 4
|
||||
/* long k6maxcc(const short *wt, const short *dp, short *Nc_out) */
|
||||
.globl k6maxcc
|
||||
.type k6maxcc,@function
|
||||
k6maxcc:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
emms
|
||||
movl 8(%ebp),%edi
|
||||
movl 12(%ebp),%esi
|
||||
movl $0,%edx /* will be maximum inner-product */
|
||||
movl $40,%ebx
|
||||
movl %ebx,%ecx /* will be index of max inner-product */
|
||||
subl $80,%esi
|
||||
.p2align 2
|
||||
.L41:
|
||||
movq (%edi),%mm0
|
||||
movq (%esi),%mm2
|
||||
pmaddwd %mm2,%mm0
|
||||
ccstep 8
|
||||
ccstep 16
|
||||
ccstep 24
|
||||
ccstep 32
|
||||
ccstep 40
|
||||
ccstep 48
|
||||
ccstep 56
|
||||
ccstep 64
|
||||
ccstep 72
|
||||
|
||||
movq %mm0,%mm1
|
||||
punpckhdq %mm0,%mm1 /* mm1 has high int32 of mm0 dup'd */
|
||||
paddd %mm1,%mm0;
|
||||
movd %mm0,%eax /* eax has result */
|
||||
|
||||
cmpl %edx,%eax
|
||||
jle .L40
|
||||
movl %eax,%edx
|
||||
movl %ebx,%ecx
|
||||
.p2align 2
|
||||
.L40:
|
||||
subl $2,%esi
|
||||
incl %ebx
|
||||
cmpl $120,%ebx
|
||||
jle .L41
|
||||
movl 16(%ebp),%eax
|
||||
movw %cx,(%eax)
|
||||
movl %edx,%eax
|
||||
emms
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe2:
|
||||
.size k6maxcc,.Lfe2-k6maxcc
|
||||
|
||||
|
||||
.align 4
|
||||
/* long k6iprod (const short *p, const short *q, int n) */
|
||||
.globl k6iprod
|
||||
.type k6iprod,@function
|
||||
k6iprod:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
emms
|
||||
pxor %mm0,%mm0
|
||||
movl 8(%ebp),%esi
|
||||
movl 12(%ebp),%edi
|
||||
movl 16(%ebp),%eax
|
||||
leal -32(%esi,%eax,2),%edx /* edx = top - 32 */
|
||||
|
||||
cmpl %edx,%esi; ja .L202
|
||||
|
||||
.p2align 2
|
||||
.L201:
|
||||
ccstep 0
|
||||
ccstep 8
|
||||
ccstep 16
|
||||
ccstep 24
|
||||
|
||||
addl $32,%esi
|
||||
addl $32,%edi
|
||||
cmpl %edx,%esi; jbe .L201
|
||||
|
||||
.p2align 2
|
||||
.L202:
|
||||
addl $24,%edx /* now edx = top-8 */
|
||||
cmpl %edx,%esi; ja .L205
|
||||
|
||||
.p2align 2
|
||||
.L203:
|
||||
ccstep 0
|
||||
|
||||
addl $8,%esi
|
||||
addl $8,%edi
|
||||
cmpl %edx,%esi; jbe .L203
|
||||
|
||||
.p2align 2
|
||||
.L205:
|
||||
addl $4,%edx /* now edx = top-4 */
|
||||
cmpl %edx,%esi; ja .L207
|
||||
|
||||
movd (%edi),%mm1
|
||||
movd (%esi),%mm2
|
||||
pmaddwd %mm2,%mm1
|
||||
paddd %mm1,%mm0
|
||||
|
||||
addl $4,%esi
|
||||
addl $4,%edi
|
||||
|
||||
.p2align 2
|
||||
.L207:
|
||||
addl $2,%edx /* now edx = top-2 */
|
||||
cmpl %edx,%esi; ja .L209
|
||||
|
||||
movswl (%edi),%eax
|
||||
movd %eax,%mm1
|
||||
movswl (%esi),%eax
|
||||
movd %eax,%mm2
|
||||
pmaddwd %mm2,%mm1
|
||||
paddd %mm1,%mm0
|
||||
|
||||
.p2align 2
|
||||
.L209:
|
||||
movq %mm0,%mm1
|
||||
punpckhdq %mm0,%mm1 /* mm1 has high int32 of mm0 dup'd */
|
||||
paddd %mm1,%mm0;
|
||||
movd %mm0,%eax /* eax has result */
|
||||
|
||||
emms
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe3:
|
||||
.size k6iprod,.Lfe3-k6iprod
|
||||
|
||||
|
||||
.align 4
|
||||
/* void k6vsraw P3((short *p, int n, int bits) */
|
||||
.globl k6vsraw
|
||||
.type k6vsraw,@function
|
||||
k6vsraw:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %esi
|
||||
movl 8(%ebp),%esi
|
||||
movl 16(%ebp),%ecx
|
||||
andl %ecx,%ecx; jle .L399
|
||||
movl 12(%ebp),%eax
|
||||
leal -16(%esi,%eax,2),%edx /* edx = top - 16 */
|
||||
emms
|
||||
movd %ecx,%mm3
|
||||
movq ones,%mm2
|
||||
psllw %mm3,%mm2; psrlw $1,%mm2
|
||||
cmpl %edx,%esi; ja .L306
|
||||
|
||||
.p2align 2
|
||||
.L302: /* 8 words per iteration */
|
||||
movq (%esi),%mm0
|
||||
movq 8(%esi),%mm1
|
||||
paddsw %mm2,%mm0
|
||||
psraw %mm3,%mm0;
|
||||
paddsw %mm2,%mm1
|
||||
psraw %mm3,%mm1;
|
||||
movq %mm0,(%esi)
|
||||
movq %mm1,8(%esi)
|
||||
addl $16,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L302
|
||||
|
||||
.p2align 2
|
||||
.L306:
|
||||
addl $12,%edx /* now edx = top-4 */
|
||||
cmpl %edx,%esi; ja .L310
|
||||
|
||||
.p2align 2
|
||||
.L308: /* do up to 6 words, two at a time */
|
||||
movd (%esi),%mm0
|
||||
paddsw %mm2,%mm0
|
||||
psraw %mm3,%mm0;
|
||||
movd %mm0,(%esi)
|
||||
addl $4,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L308
|
||||
|
||||
.p2align 2
|
||||
.L310:
|
||||
addl $2,%edx /* now edx = top-2 */
|
||||
cmpl %edx,%esi; ja .L315
|
||||
|
||||
movzwl (%esi),%eax
|
||||
movd %eax,%mm0
|
||||
paddsw %mm2,%mm0
|
||||
psraw %mm3,%mm0;
|
||||
movd %mm0,%eax
|
||||
movw %ax,(%esi)
|
||||
|
||||
.p2align 2
|
||||
.L315:
|
||||
emms
|
||||
.L399:
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
.Lfe4:
|
||||
.size k6vsraw,.Lfe4-k6vsraw
|
||||
|
||||
.align 4
|
||||
/* void k6vsllw P3((short *p, int n, int bits) */
|
||||
.globl k6vsllw
|
||||
.type k6vsllw,@function
|
||||
k6vsllw:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %esi
|
||||
movl 8(%ebp),%esi
|
||||
movl 16(%ebp),%ecx
|
||||
andl %ecx,%ecx; jle .L499
|
||||
movl 12(%ebp),%eax
|
||||
leal -16(%esi,%eax,2),%edx /* edx = top - 16 */
|
||||
emms
|
||||
movd %ecx,%mm3
|
||||
cmpl %edx,%esi; ja .L406
|
||||
|
||||
.p2align 2
|
||||
.L402: /* 8 words per iteration */
|
||||
movq (%esi),%mm0
|
||||
movq 8(%esi),%mm1
|
||||
psllw %mm3,%mm0;
|
||||
psllw %mm3,%mm1;
|
||||
movq %mm0,(%esi)
|
||||
movq %mm1,8(%esi)
|
||||
addl $16,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L402
|
||||
|
||||
.p2align 2
|
||||
.L406:
|
||||
addl $12,%edx /* now edx = top-4 */
|
||||
cmpl %edx,%esi; ja .L410
|
||||
|
||||
.p2align 2
|
||||
.L408: /* do up to 6 words, two at a time */
|
||||
movd (%esi),%mm0
|
||||
psllw %mm3,%mm0;
|
||||
movd %mm0,(%esi)
|
||||
addl $4,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L408
|
||||
|
||||
.p2align 2
|
||||
.L410:
|
||||
addl $2,%edx /* now edx = top-2 */
|
||||
cmpl %edx,%esi; ja .L415
|
||||
|
||||
movzwl (%esi),%eax
|
||||
movd %eax,%mm0
|
||||
psllw %mm3,%mm0;
|
||||
movd %mm0,%eax
|
||||
movw %ax,(%esi)
|
||||
|
||||
.p2align 2
|
||||
.L415:
|
||||
emms
|
||||
.L499:
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
.Lfe5:
|
||||
.size k6vsllw,.Lfe5-k6vsllw
|
||||
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
.type extremes,@object
|
||||
.size extremes,8
|
||||
extremes:
|
||||
.long 0x80008000
|
||||
.long 0x7fff7fff
|
||||
.type ones,@object
|
||||
.size ones,8
|
||||
ones:
|
||||
.long 0x00010001
|
||||
.long 0x00010001
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/* long k6maxmin (const short *p, int n, short *out) */
|
||||
.globl k6maxmin
|
||||
.type k6maxmin,@function
|
||||
k6maxmin:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %esi
|
||||
emms
|
||||
movl 8(%ebp),%esi
|
||||
movl 12(%ebp),%eax
|
||||
leal -8(%esi,%eax,2),%edx
|
||||
|
||||
cmpl %edx,%esi
|
||||
jbe .L52
|
||||
movd extremes,%mm0
|
||||
movd extremes+4,%mm1
|
||||
jmp .L58
|
||||
|
||||
.p2align 2
|
||||
.L52:
|
||||
movq (%esi),%mm0 /* mm0 will be max's */
|
||||
movq %mm0,%mm1 /* mm1 will be min's */
|
||||
addl $8,%esi
|
||||
cmpl %edx,%esi
|
||||
ja .L56
|
||||
|
||||
.p2align 2
|
||||
.L54:
|
||||
movq (%esi),%mm2
|
||||
|
||||
movq %mm2,%mm3
|
||||
pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */
|
||||
movq %mm3,%mm4
|
||||
pand %mm2,%mm3 /* mm3 is mm2 masked to new max's */
|
||||
pandn %mm0,%mm4 /* mm4 is mm0 masked to its max's */
|
||||
por %mm3,%mm4
|
||||
movq %mm4,%mm0 /* now mm0 is updated max's */
|
||||
|
||||
movq %mm1,%mm3
|
||||
pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */
|
||||
pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */
|
||||
por %mm3,%mm2
|
||||
movq %mm2,%mm1 /* now mm1 is updated min's */
|
||||
|
||||
addl $8,%esi
|
||||
cmpl %edx,%esi
|
||||
jbe .L54
|
||||
|
||||
.p2align 2
|
||||
.L56: /* merge down the 4-word max/mins to lower 2 words */
|
||||
|
||||
movq %mm0,%mm2
|
||||
psrlq $32,%mm2
|
||||
movq %mm2,%mm3
|
||||
pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new max's */
|
||||
pandn %mm0,%mm3 /* mm3 is mm0 masked to its max's */
|
||||
por %mm3,%mm2
|
||||
movq %mm2,%mm0 /* now mm0 is updated max's */
|
||||
|
||||
movq %mm1,%mm2
|
||||
psrlq $32,%mm2
|
||||
movq %mm1,%mm3
|
||||
pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */
|
||||
pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */
|
||||
por %mm3,%mm2
|
||||
movq %mm2,%mm1 /* now mm1 is updated min's */
|
||||
|
||||
.p2align 2
|
||||
.L58:
|
||||
addl $4,%edx /* now dx = top-4 */
|
||||
cmpl %edx,%esi
|
||||
ja .L62
|
||||
/* here, there are >= 2 words of input remaining */
|
||||
movd (%esi),%mm2
|
||||
|
||||
movq %mm2,%mm3
|
||||
pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */
|
||||
movq %mm3,%mm4
|
||||
pand %mm2,%mm3 /* mm3 is mm2 masked to new max's */
|
||||
pandn %mm0,%mm4 /* mm4 is mm0 masked to its max's */
|
||||
por %mm3,%mm4
|
||||
movq %mm4,%mm0 /* now mm0 is updated max's */
|
||||
|
||||
movq %mm1,%mm3
|
||||
pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */
|
||||
pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */
|
||||
por %mm3,%mm2
|
||||
movq %mm2,%mm1 /* now mm1 is updated min's */
|
||||
|
||||
addl $4,%esi
|
||||
|
||||
.p2align 2
|
||||
.L62:
|
||||
/* merge down the 2-word max/mins to 1 word */
|
||||
|
||||
movq %mm0,%mm2
|
||||
psrlq $16,%mm2
|
||||
movq %mm2,%mm3
|
||||
pcmpgtw %mm0,%mm3 /* mm3 is bitmask for words where mm2 > mm0 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new max's */
|
||||
pandn %mm0,%mm3 /* mm3 is mm0 masked to its max's */
|
||||
por %mm3,%mm2
|
||||
movd %mm2,%ecx /* cx is max so far */
|
||||
|
||||
movq %mm1,%mm2
|
||||
psrlq $16,%mm2
|
||||
movq %mm1,%mm3
|
||||
pcmpgtw %mm2,%mm3 /* mm3 is bitmask for words where mm2 < mm1 */
|
||||
pand %mm3,%mm2 /* mm2 is mm2 masked to new min's */
|
||||
pandn %mm1,%mm3 /* mm3 is mm1 masked to its min's */
|
||||
por %mm3,%mm2
|
||||
movd %mm2,%eax /* ax is min so far */
|
||||
|
||||
addl $2,%edx /* now dx = top-2 */
|
||||
cmpl %edx,%esi
|
||||
ja .L65
|
||||
|
||||
/* here, there is one word of input left */
|
||||
cmpw (%esi),%cx
|
||||
jge .L64
|
||||
movw (%esi),%cx
|
||||
.p2align 2
|
||||
.L64:
|
||||
cmpw (%esi),%ax
|
||||
jle .L65
|
||||
movw (%esi),%ax
|
||||
|
||||
.p2align 2
|
||||
.L65: /* (finally!) cx is the max, ax the min */
|
||||
movswl %cx,%ecx
|
||||
movswl %ax,%eax
|
||||
|
||||
movl 16(%ebp),%edx /* ptr to output max,min vals */
|
||||
andl %edx,%edx; jz .L77
|
||||
movw %cx,(%edx) /* max */
|
||||
movw %ax,2(%edx) /* min */
|
||||
.p2align 2
|
||||
.L77:
|
||||
/* now calculate max absolute val */
|
||||
negl %eax
|
||||
cmpl %ecx,%eax
|
||||
jge .L81
|
||||
movl %ecx,%eax
|
||||
.p2align 2
|
||||
.L81:
|
||||
emms
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
.Lfe6:
|
||||
.size k6maxmin,.Lfe6-k6maxmin
|
||||
|
||||
/* void Short_term_analysis_filtering (short *u0, const short *rp0, int kn, short *s) */
|
||||
.equiv pm_u0,8
|
||||
.equiv pm_rp0,12
|
||||
.equiv pm_kn,16
|
||||
.equiv pm_s,20
|
||||
.equiv lv_u_top,-4
|
||||
.equiv lv_s_top,-8
|
||||
.equiv lv_rp,-40 /* local version of rp0 with each word twice */
|
||||
.align 4
|
||||
.globl Short_term_analysis_filteringx
|
||||
.type Short_term_analysis_filteringx,@function
|
||||
Short_term_analysis_filteringx:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
subl $40,%esp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
|
||||
movl pm_rp0(%ebp),%esi;
|
||||
leal lv_rp(%ebp),%edi;
|
||||
cld
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
emms
|
||||
movl $0x4000,%eax;
|
||||
movd %eax,%mm4;
|
||||
punpckldq %mm4,%mm4 /* (0x00004000,0x00004000) for rounding dword product pairs */
|
||||
|
||||
movl pm_u0(%ebp),%eax
|
||||
addl $16,%eax
|
||||
movl %eax,lv_u_top(%ebp) /* UTOP */
|
||||
movl pm_s(%ebp),%edx /* edx is local s ptr throughout below */
|
||||
movl pm_kn(%ebp),%eax
|
||||
leal (%edx,%eax,2),%eax
|
||||
movl %eax,lv_s_top(%ebp)
|
||||
cmpl %eax,%edx
|
||||
jae .L179
|
||||
.p2align 2
|
||||
.L181:
|
||||
leal lv_rp(%ebp),%esi /* RP */
|
||||
movl pm_u0(%ebp),%edi /* U */
|
||||
movw (%edx),%ax /* (0,DI) */
|
||||
roll $16,%eax
|
||||
movw (%edx),%ax /* (DI,DI) */
|
||||
.p2align 2
|
||||
.L185: /* RP is %esi */
|
||||
movl %eax,%ecx
|
||||
movw (%edi),%ax /* (DI,U) */
|
||||
movd (%esi),%mm3 /* mm3 is (0,0,RP,RP) */
|
||||
movw %cx,(%edi)
|
||||
|
||||
movd %eax,%mm2 /* mm2 is (0,0,DI,U) */
|
||||
rorl $16,%eax
|
||||
movd %eax,%mm1 /* mm1 is (0,0,U,DI) */
|
||||
|
||||
movq %mm1,%mm0
|
||||
pmullw %mm3,%mm0
|
||||
pmulhw %mm3,%mm1
|
||||
punpcklwd %mm1,%mm0 /* mm0 is (RP*U,RP*DI) */
|
||||
paddd %mm4,%mm0 /* mm4 is 0x00004000,0x00004000 */
|
||||
psrad $15,%mm0 /* (RP*U,RP*DI) adjusted */
|
||||
packssdw %mm0,%mm0 /* (*,*,RP*U,RP*DI) adjusted and saturated to word */
|
||||
paddsw %mm2,%mm0 /* mm0 is (?,?, DI', U') */
|
||||
movd %mm0,%eax /* (DI,U') */
|
||||
|
||||
addl $2,%edi
|
||||
addl $4,%esi
|
||||
cmpl lv_u_top(%ebp),%edi
|
||||
jb .L185
|
||||
|
||||
rorl $16,%eax
|
||||
movw %ax,(%edx) /* last DI goes to *s */
|
||||
addl $2,%edx /* next s */
|
||||
cmpl lv_s_top(%ebp),%edx
|
||||
jb .L181
|
||||
.p2align 2
|
||||
.L179:
|
||||
emms
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe7:
|
||||
.size Short_term_analysis_filteringx,.Lfe7-Short_term_analysis_filteringx
|
||||
|
||||
.end
|
||||
|
||||
/* 'as' macro's seem to be case-insensitive */
|
||||
.macro STEP n
|
||||
.if \n
|
||||
movd \n(%esi),%mm3 /* mm3 is (0,0,RP,RP) */
|
||||
.else
|
||||
movd (%esi),%mm3 /* mm3 is (0,0,RP,RP) */
|
||||
.endif
|
||||
movq %mm5,%mm1;
|
||||
movd %mm4,%ecx; movw %cx,%ax /* (DI,U) */
|
||||
psllq $48,%mm1; psrlq $16,%mm4; por %mm1,%mm4
|
||||
psllq $48,%mm0; psrlq $16,%mm5; por %mm0,%mm5
|
||||
|
||||
movd %eax,%mm2 /* mm2 is (0,0,DI,U) */
|
||||
rorl $16,%eax
|
||||
movd %eax,%mm1 /* mm1 is (0,0,U,DI) */
|
||||
|
||||
movq %mm1,%mm0
|
||||
pmullw %mm3,%mm0
|
||||
pmulhw %mm3,%mm1
|
||||
punpcklwd %mm1,%mm0 /* mm0 is (RP*U,RP*DI) */
|
||||
paddd %mm6,%mm0 /* mm6 is 0x00004000,0x00004000 */
|
||||
psrad $15,%mm0 /* (RP*U,RP*DI) adjusted */
|
||||
packssdw %mm0,%mm0 /* (*,*,RP*U,RP*DI) adjusted and saturated to word */
|
||||
paddsw %mm2,%mm0 /* mm0 is (?,?, DI', U') */
|
||||
movd %mm0,%eax /* (DI,U') */
|
||||
.endm
|
||||
|
||||
/* void Short_term_analysis_filtering (short *u0, const short *rp0, int kn, short *s) */
|
||||
.equiv pm_u0,8
|
||||
.equiv pm_rp0,12
|
||||
.equiv pm_kn,16
|
||||
.equiv pm_s,20
|
||||
.equiv lv_rp_top,-4
|
||||
.equiv lv_s_top,-8
|
||||
.equiv lv_rp,-40 /* local version of rp0 with each word twice */
|
||||
.align 4
|
||||
.globl Short_term_analysis_filteringx
|
||||
.type Short_term_analysis_filteringx,@function
|
||||
Short_term_analysis_filteringx:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
subl $56,%esp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
|
||||
movl pm_rp0(%ebp),%esi;
|
||||
leal lv_rp(%ebp),%edi;
|
||||
cld
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
lodsw; stosw; stosw
|
||||
movl %edi,lv_rp_top(%ebp)
|
||||
emms
|
||||
|
||||
movl $0x4000,%eax;
|
||||
movd %eax,%mm6;
|
||||
punpckldq %mm6,%mm6 /* (0x00004000,0x00004000) for rounding dword product pairs */
|
||||
|
||||
movl pm_u0(%ebp),%ebx
|
||||
movq (%ebx),%mm4; movq 8(%ebx),%mm5 /* the 8 u's */
|
||||
movl pm_s(%ebp),%edx /* edx is local s ptr throughout below */
|
||||
movl pm_kn(%ebp),%eax
|
||||
leal (%edx,%eax,2),%eax
|
||||
movl %eax,lv_s_top(%ebp)
|
||||
cmpl %eax,%edx
|
||||
jae .L179
|
||||
.p2align 2
|
||||
.L181:
|
||||
leal lv_rp(%ebp),%esi /* RP */
|
||||
movw (%edx),%ax /* (0,DI) */
|
||||
roll $16,%eax
|
||||
movw (%edx),%ax /* (DI,DI) */
|
||||
movd %eax,%mm0
|
||||
.p2align 2
|
||||
.L185: /* RP is %esi */
|
||||
step 0
|
||||
step 4
|
||||
step 8
|
||||
step 12
|
||||
/*
|
||||
step 16
|
||||
step 20
|
||||
step 24
|
||||
step 28
|
||||
*/
|
||||
addl $16,%esi
|
||||
cmpl lv_rp_top(%ebp),%esi
|
||||
jb .L185
|
||||
|
||||
rorl $16,%eax
|
||||
movw %ax,(%edx) /* last DI goes to *s */
|
||||
addl $2,%edx /* next s */
|
||||
cmpl lv_s_top(%ebp),%edx
|
||||
jb .L181
|
||||
.L179:
|
||||
movq %mm4,(%ebx); movq %mm5,8(%ebx) /* the 8 u's */
|
||||
emms
|
||||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
.Lfe7:
|
||||
.size Short_term_analysis_filteringx,.Lfe7-Short_term_analysis_filteringx
|
||||
.ident "GCC: (GNU) 2.95.2 19991109 (Debian GNU/Linux)"
|
||||
+954
@@ -0,0 +1,954 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
#ifdef K6OPT
|
||||
#include "k6opt.h"
|
||||
#endif
|
||||
/*
|
||||
* 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This module computes the LTP gain (bc) and the LTP lag (Nc)
|
||||
* for the long term analysis filter. This is done by calculating a
|
||||
* maximum of the cross-correlation function between the current
|
||||
* sub-segment short term residual signal d[0..39] (output of
|
||||
* the short term analysis filter; for simplification the index
|
||||
* of this array begins at 0 and ends at 39 for each sub-segment of the
|
||||
* RPE-LTP analysis) and the previous reconstructed short term
|
||||
* residual signal dp[ -120 .. -1 ]. A dynamic scaling must be
|
||||
* performed to avoid overflow.
|
||||
*/
|
||||
|
||||
/* The next procedure exists in six versions. First two integer
|
||||
* version (if USE_FLOAT_MUL is not defined); then four floating
|
||||
* point versions, twice with proper scaling (USE_FLOAT_MUL defined),
|
||||
* once without (USE_FLOAT_MUL and FAST defined, and fast run-time
|
||||
* option used). Every pair has first a Cut version (see the -C
|
||||
* option to toast or the LTP_CUT option to gsm_option()), then the
|
||||
* uncut one. (For a detailed explanation of why this is altogether
|
||||
* a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered
|
||||
* Harmful''.)
|
||||
*/
|
||||
|
||||
#ifndef USE_FLOAT_MUL
|
||||
|
||||
#ifdef LTP_CUT
|
||||
|
||||
static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out),
|
||||
|
||||
struct gsm_state * st,
|
||||
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
word wt[40];
|
||||
|
||||
longword L_result;
|
||||
longword L_max, L_power;
|
||||
word R, S, dmax, scal, best_k;
|
||||
word ltp_cut;
|
||||
|
||||
register word temp, wt_k;
|
||||
|
||||
/* Search of the optimum scaling of d[0..39].
|
||||
*/
|
||||
dmax = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
temp = d[k];
|
||||
temp = GSM_ABS( temp );
|
||||
if (temp > dmax) {
|
||||
dmax = temp;
|
||||
best_k = k;
|
||||
}
|
||||
}
|
||||
temp = 0;
|
||||
if (dmax == 0) scal = 0;
|
||||
else {
|
||||
assert(dmax > 0);
|
||||
temp = gsm_norm( (longword)dmax << 16 );
|
||||
}
|
||||
if (temp > 6) scal = 0;
|
||||
else scal = 6 - temp;
|
||||
assert(scal >= 0);
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
wt_k = SASR(d[best_k], scal);
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda++) {
|
||||
L_result = (longword)wt_k * dp[best_k - lambda];
|
||||
if (L_result > L_max) {
|
||||
Nc = lambda;
|
||||
L_max = L_result;
|
||||
}
|
||||
}
|
||||
*Nc_out = Nc;
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max
|
||||
*/
|
||||
assert(scal <= 100 && scal >= -100);
|
||||
L_max = L_max >> (6 - scal); /* sub(6, scal) */
|
||||
|
||||
assert( Nc <= 120 && Nc >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
L_power = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
register longword L_temp;
|
||||
|
||||
L_temp = SASR( dp[k - Nc], 3 );
|
||||
L_power += L_temp * L_temp;
|
||||
}
|
||||
L_power <<= 1; /* from L_MULT */
|
||||
|
||||
/* Normalization of L_max and L_power
|
||||
*/
|
||||
|
||||
if (L_max <= 0) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
temp = gsm_norm( L_power );
|
||||
|
||||
R = SASR( L_max << temp, 16 );
|
||||
S = SASR( L_power << temp, 16 );
|
||||
|
||||
/* Coding of the LTP gain
|
||||
*/
|
||||
|
||||
/* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#endif /* LTP_CUT */
|
||||
|
||||
static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out),
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
word wt[40];
|
||||
|
||||
longword L_max, L_power;
|
||||
word R, S, dmax, scal;
|
||||
register word temp;
|
||||
|
||||
/* Search of the optimum scaling of d[0..39].
|
||||
*/
|
||||
dmax = 0;
|
||||
|
||||
for (k = 0; k <= 39; k++) {
|
||||
temp = d[k];
|
||||
temp = GSM_ABS( temp );
|
||||
if (temp > dmax) dmax = temp;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
if (dmax == 0) scal = 0;
|
||||
else {
|
||||
assert(dmax > 0);
|
||||
temp = gsm_norm( (longword)dmax << 16 );
|
||||
}
|
||||
|
||||
if (temp > 6) scal = 0;
|
||||
else scal = 6 - temp;
|
||||
|
||||
assert(scal >= 0);
|
||||
|
||||
/* Initialization of a working array wt
|
||||
*/
|
||||
|
||||
for (k = 0; k <= 39; k++) wt[k] = SASR( d[k], scal );
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
# ifdef K6OPT
|
||||
L_max = k6maxcc(wt,dp,&Nc);
|
||||
# else
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda++) {
|
||||
|
||||
# undef STEP
|
||||
# define STEP(k) (longword)wt[k] * dp[k - lambda]
|
||||
|
||||
register longword L_result;
|
||||
|
||||
L_result = STEP(0) ; L_result += STEP(1) ;
|
||||
L_result += STEP(2) ; L_result += STEP(3) ;
|
||||
L_result += STEP(4) ; L_result += STEP(5) ;
|
||||
L_result += STEP(6) ; L_result += STEP(7) ;
|
||||
L_result += STEP(8) ; L_result += STEP(9) ;
|
||||
L_result += STEP(10) ; L_result += STEP(11) ;
|
||||
L_result += STEP(12) ; L_result += STEP(13) ;
|
||||
L_result += STEP(14) ; L_result += STEP(15) ;
|
||||
L_result += STEP(16) ; L_result += STEP(17) ;
|
||||
L_result += STEP(18) ; L_result += STEP(19) ;
|
||||
L_result += STEP(20) ; L_result += STEP(21) ;
|
||||
L_result += STEP(22) ; L_result += STEP(23) ;
|
||||
L_result += STEP(24) ; L_result += STEP(25) ;
|
||||
L_result += STEP(26) ; L_result += STEP(27) ;
|
||||
L_result += STEP(28) ; L_result += STEP(29) ;
|
||||
L_result += STEP(30) ; L_result += STEP(31) ;
|
||||
L_result += STEP(32) ; L_result += STEP(33) ;
|
||||
L_result += STEP(34) ; L_result += STEP(35) ;
|
||||
L_result += STEP(36) ; L_result += STEP(37) ;
|
||||
L_result += STEP(38) ; L_result += STEP(39) ;
|
||||
|
||||
if (L_result > L_max) {
|
||||
|
||||
Nc = lambda;
|
||||
L_max = L_result;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
*Nc_out = Nc;
|
||||
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max
|
||||
*/
|
||||
assert(scal <= 100 && scal >= -100);
|
||||
L_max = L_max >> (6 - scal); /* sub(6, scal) */
|
||||
|
||||
assert( Nc <= 120 && Nc >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
L_power = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
register longword L_temp;
|
||||
|
||||
L_temp = SASR( dp[k - Nc], 3 );
|
||||
L_power += L_temp * L_temp;
|
||||
}
|
||||
L_power <<= 1; /* from L_MULT */
|
||||
|
||||
/* Normalization of L_max and L_power
|
||||
*/
|
||||
|
||||
if (L_max <= 0) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
temp = gsm_norm( L_power );
|
||||
|
||||
R = SASR( L_max << temp, 16 );
|
||||
S = SASR( L_power << temp, 16 );
|
||||
|
||||
/* Coding of the LTP gain
|
||||
*/
|
||||
|
||||
/* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#else /* USE_FLOAT_MUL */
|
||||
|
||||
#ifdef LTP_CUT
|
||||
|
||||
static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out),
|
||||
struct gsm_state * st, /* IN */
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
word ltp_cut;
|
||||
|
||||
float wt_float[40];
|
||||
float dp_float_base[120], * dp_float = dp_float_base + 120;
|
||||
|
||||
longword L_max, L_power;
|
||||
word R, S, dmax, scal;
|
||||
register word temp;
|
||||
|
||||
/* Search of the optimum scaling of d[0..39].
|
||||
*/
|
||||
dmax = 0;
|
||||
|
||||
for (k = 0; k <= 39; k++) {
|
||||
temp = d[k];
|
||||
temp = GSM_ABS( temp );
|
||||
if (temp > dmax) dmax = temp;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
if (dmax == 0) scal = 0;
|
||||
else {
|
||||
assert(dmax > 0);
|
||||
temp = gsm_norm( (longword)dmax << 16 );
|
||||
}
|
||||
|
||||
if (temp > 6) scal = 0;
|
||||
else scal = 6 - temp;
|
||||
|
||||
assert(scal >= 0);
|
||||
ltp_cut = (longword)SASR(dmax, scal) * st->ltp_cut / 100;
|
||||
|
||||
|
||||
/* Initialization of a working array wt
|
||||
*/
|
||||
|
||||
for (k = 0; k < 40; k++) {
|
||||
register word w = SASR( d[k], scal );
|
||||
if (w < 0 ? w > -ltp_cut : w < ltp_cut) {
|
||||
wt_float[k] = 0.0;
|
||||
}
|
||||
else {
|
||||
wt_float[k] = w;
|
||||
}
|
||||
}
|
||||
for (k = -120; k < 0; k++) dp_float[k] = dp[k];
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda += 9) {
|
||||
|
||||
/* Calculate L_result for l = lambda .. lambda + 9.
|
||||
*/
|
||||
register float *lp = dp_float - lambda;
|
||||
|
||||
register float W;
|
||||
register float a = lp[-8], b = lp[-7], c = lp[-6],
|
||||
d = lp[-5], e = lp[-4], f = lp[-3],
|
||||
g = lp[-2], h = lp[-1];
|
||||
register float E;
|
||||
register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
|
||||
S5 = 0, S6 = 0, S7 = 0, S8 = 0;
|
||||
|
||||
# undef STEP
|
||||
# define STEP(K, a, b, c, d, e, f, g, h) \
|
||||
if ((W = wt_float[K]) != 0.0) { \
|
||||
E = W * a; S8 += E; \
|
||||
E = W * b; S7 += E; \
|
||||
E = W * c; S6 += E; \
|
||||
E = W * d; S5 += E; \
|
||||
E = W * e; S4 += E; \
|
||||
E = W * f; S3 += E; \
|
||||
E = W * g; S2 += E; \
|
||||
E = W * h; S1 += E; \
|
||||
a = lp[K]; \
|
||||
E = W * a; S0 += E; } else (a = lp[K])
|
||||
|
||||
# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h)
|
||||
# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a)
|
||||
# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b)
|
||||
# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c)
|
||||
# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d)
|
||||
# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e)
|
||||
# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f)
|
||||
# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g)
|
||||
|
||||
STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3);
|
||||
STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7);
|
||||
|
||||
STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11);
|
||||
STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15);
|
||||
|
||||
STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19);
|
||||
STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23);
|
||||
|
||||
STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27);
|
||||
STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31);
|
||||
|
||||
STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35);
|
||||
STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39);
|
||||
|
||||
if (S0 > L_max) { L_max = S0; Nc = lambda; }
|
||||
if (S1 > L_max) { L_max = S1; Nc = lambda + 1; }
|
||||
if (S2 > L_max) { L_max = S2; Nc = lambda + 2; }
|
||||
if (S3 > L_max) { L_max = S3; Nc = lambda + 3; }
|
||||
if (S4 > L_max) { L_max = S4; Nc = lambda + 4; }
|
||||
if (S5 > L_max) { L_max = S5; Nc = lambda + 5; }
|
||||
if (S6 > L_max) { L_max = S6; Nc = lambda + 6; }
|
||||
if (S7 > L_max) { L_max = S7; Nc = lambda + 7; }
|
||||
if (S8 > L_max) { L_max = S8; Nc = lambda + 8; }
|
||||
|
||||
}
|
||||
*Nc_out = Nc;
|
||||
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max
|
||||
*/
|
||||
assert(scal <= 100 && scal >= -100);
|
||||
L_max = L_max >> (6 - scal); /* sub(6, scal) */
|
||||
|
||||
assert( Nc <= 120 && Nc >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
L_power = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
register longword L_temp;
|
||||
|
||||
L_temp = SASR( dp[k - Nc], 3 );
|
||||
L_power += L_temp * L_temp;
|
||||
}
|
||||
L_power <<= 1; /* from L_MULT */
|
||||
|
||||
/* Normalization of L_max and L_power
|
||||
*/
|
||||
|
||||
if (L_max <= 0) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
temp = gsm_norm( L_power );
|
||||
|
||||
R = SASR( L_max << temp, 16 );
|
||||
S = SASR( L_power << temp, 16 );
|
||||
|
||||
/* Coding of the LTP gain
|
||||
*/
|
||||
|
||||
/* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#endif /* LTP_CUT */
|
||||
|
||||
static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out),
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
|
||||
float wt_float[40];
|
||||
float dp_float_base[120], * dp_float = dp_float_base + 120;
|
||||
|
||||
longword L_max, L_power;
|
||||
word R, S, dmax, scal;
|
||||
register word temp;
|
||||
|
||||
/* Search of the optimum scaling of d[0..39].
|
||||
*/
|
||||
dmax = 0;
|
||||
|
||||
for (k = 0; k <= 39; k++) {
|
||||
temp = d[k];
|
||||
temp = GSM_ABS( temp );
|
||||
if (temp > dmax) dmax = temp;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
if (dmax == 0) scal = 0;
|
||||
else {
|
||||
assert(dmax > 0);
|
||||
temp = gsm_norm( (longword)dmax << 16 );
|
||||
}
|
||||
|
||||
if (temp > 6) scal = 0;
|
||||
else scal = 6 - temp;
|
||||
|
||||
assert(scal >= 0);
|
||||
|
||||
/* Initialization of a working array wt
|
||||
*/
|
||||
|
||||
for (k = 0; k < 40; k++) wt_float[k] = SASR( d[k], scal );
|
||||
for (k = -120; k < 0; k++) dp_float[k] = dp[k];
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda += 9) {
|
||||
|
||||
/* Calculate L_result for l = lambda .. lambda + 9.
|
||||
*/
|
||||
register float *lp = dp_float - lambda;
|
||||
|
||||
register float W;
|
||||
register float a = lp[-8], b = lp[-7], c = lp[-6],
|
||||
d = lp[-5], e = lp[-4], f = lp[-3],
|
||||
g = lp[-2], h = lp[-1];
|
||||
register float E;
|
||||
register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
|
||||
S5 = 0, S6 = 0, S7 = 0, S8 = 0;
|
||||
|
||||
# undef STEP
|
||||
# define STEP(K, a, b, c, d, e, f, g, h) \
|
||||
W = wt_float[K]; \
|
||||
E = W * a; S8 += E; \
|
||||
E = W * b; S7 += E; \
|
||||
E = W * c; S6 += E; \
|
||||
E = W * d; S5 += E; \
|
||||
E = W * e; S4 += E; \
|
||||
E = W * f; S3 += E; \
|
||||
E = W * g; S2 += E; \
|
||||
E = W * h; S1 += E; \
|
||||
a = lp[K]; \
|
||||
E = W * a; S0 += E
|
||||
|
||||
# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h)
|
||||
# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a)
|
||||
# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b)
|
||||
# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c)
|
||||
# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d)
|
||||
# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e)
|
||||
# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f)
|
||||
# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g)
|
||||
|
||||
STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3);
|
||||
STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7);
|
||||
|
||||
STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11);
|
||||
STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15);
|
||||
|
||||
STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19);
|
||||
STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23);
|
||||
|
||||
STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27);
|
||||
STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31);
|
||||
|
||||
STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35);
|
||||
STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39);
|
||||
|
||||
if (S0 > L_max) { L_max = S0; Nc = lambda; }
|
||||
if (S1 > L_max) { L_max = S1; Nc = lambda + 1; }
|
||||
if (S2 > L_max) { L_max = S2; Nc = lambda + 2; }
|
||||
if (S3 > L_max) { L_max = S3; Nc = lambda + 3; }
|
||||
if (S4 > L_max) { L_max = S4; Nc = lambda + 4; }
|
||||
if (S5 > L_max) { L_max = S5; Nc = lambda + 5; }
|
||||
if (S6 > L_max) { L_max = S6; Nc = lambda + 6; }
|
||||
if (S7 > L_max) { L_max = S7; Nc = lambda + 7; }
|
||||
if (S8 > L_max) { L_max = S8; Nc = lambda + 8; }
|
||||
}
|
||||
*Nc_out = Nc;
|
||||
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max
|
||||
*/
|
||||
assert(scal <= 100 && scal >= -100);
|
||||
L_max = L_max >> (6 - scal); /* sub(6, scal) */
|
||||
|
||||
assert( Nc <= 120 && Nc >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
L_power = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
register longword L_temp;
|
||||
|
||||
L_temp = SASR( dp[k - Nc], 3 );
|
||||
L_power += L_temp * L_temp;
|
||||
}
|
||||
L_power <<= 1; /* from L_MULT */
|
||||
|
||||
/* Normalization of L_max and L_power
|
||||
*/
|
||||
|
||||
if (L_max <= 0) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
temp = gsm_norm( L_power );
|
||||
|
||||
R = SASR( L_max << temp, 16 );
|
||||
S = SASR( L_power << temp, 16 );
|
||||
|
||||
/* Coding of the LTP gain
|
||||
*/
|
||||
|
||||
/* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#ifdef FAST
|
||||
#ifdef LTP_CUT
|
||||
|
||||
static void Cut_Fast_Calculation_of_the_LTP_parameters P5((st,
|
||||
d,dp,bc_out,Nc_out),
|
||||
struct gsm_state * st, /* IN */
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
register float wt_float;
|
||||
word Nc, bc;
|
||||
word wt_max, best_k, ltp_cut;
|
||||
|
||||
float dp_float_base[120], * dp_float = dp_float_base + 120;
|
||||
|
||||
register float L_result, L_max, L_power;
|
||||
|
||||
wt_max = 0;
|
||||
|
||||
for (k = 0; k < 40; ++k) {
|
||||
if ( d[k] > wt_max) wt_max = d[best_k = k];
|
||||
else if (-d[k] > wt_max) wt_max = -d[best_k = k];
|
||||
}
|
||||
|
||||
assert(wt_max >= 0);
|
||||
wt_float = (float)wt_max;
|
||||
|
||||
for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k];
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda++) {
|
||||
L_result = wt_float * dp_float[best_k - lambda];
|
||||
if (L_result > L_max) {
|
||||
Nc = lambda;
|
||||
L_max = L_result;
|
||||
}
|
||||
}
|
||||
|
||||
*Nc_out = Nc;
|
||||
if (L_max <= 0.) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
dp_float -= Nc;
|
||||
L_power = 0;
|
||||
for (k = 0; k < 40; ++k) {
|
||||
register float f = dp_float[k];
|
||||
L_power += f * f;
|
||||
}
|
||||
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Coding of the LTP gain
|
||||
* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
lambda = L_max / L_power * 32768.;
|
||||
for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#endif /* LTP_CUT */
|
||||
|
||||
static void Fast_Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out),
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
|
||||
float wt_float[40];
|
||||
float dp_float_base[120], * dp_float = dp_float_base + 120;
|
||||
|
||||
register float L_max, L_power;
|
||||
|
||||
for (k = 0; k < 40; ++k) wt_float[k] = (float)d[k];
|
||||
for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k];
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda += 9) {
|
||||
|
||||
/* Calculate L_result for l = lambda .. lambda + 9.
|
||||
*/
|
||||
register float *lp = dp_float - lambda;
|
||||
|
||||
register float W;
|
||||
register float a = lp[-8], b = lp[-7], c = lp[-6],
|
||||
d = lp[-5], e = lp[-4], f = lp[-3],
|
||||
g = lp[-2], h = lp[-1];
|
||||
register float E;
|
||||
register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
|
||||
S5 = 0, S6 = 0, S7 = 0, S8 = 0;
|
||||
|
||||
# undef STEP
|
||||
# define STEP(K, a, b, c, d, e, f, g, h) \
|
||||
W = wt_float[K]; \
|
||||
E = W * a; S8 += E; \
|
||||
E = W * b; S7 += E; \
|
||||
E = W * c; S6 += E; \
|
||||
E = W * d; S5 += E; \
|
||||
E = W * e; S4 += E; \
|
||||
E = W * f; S3 += E; \
|
||||
E = W * g; S2 += E; \
|
||||
E = W * h; S1 += E; \
|
||||
a = lp[K]; \
|
||||
E = W * a; S0 += E
|
||||
|
||||
# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h)
|
||||
# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a)
|
||||
# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b)
|
||||
# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c)
|
||||
# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d)
|
||||
# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e)
|
||||
# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f)
|
||||
# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g)
|
||||
|
||||
STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3);
|
||||
STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7);
|
||||
|
||||
STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11);
|
||||
STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15);
|
||||
|
||||
STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19);
|
||||
STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23);
|
||||
|
||||
STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27);
|
||||
STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31);
|
||||
|
||||
STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35);
|
||||
STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39);
|
||||
|
||||
if (S0 > L_max) { L_max = S0; Nc = lambda; }
|
||||
if (S1 > L_max) { L_max = S1; Nc = lambda + 1; }
|
||||
if (S2 > L_max) { L_max = S2; Nc = lambda + 2; }
|
||||
if (S3 > L_max) { L_max = S3; Nc = lambda + 3; }
|
||||
if (S4 > L_max) { L_max = S4; Nc = lambda + 4; }
|
||||
if (S5 > L_max) { L_max = S5; Nc = lambda + 5; }
|
||||
if (S6 > L_max) { L_max = S6; Nc = lambda + 6; }
|
||||
if (S7 > L_max) { L_max = S7; Nc = lambda + 7; }
|
||||
if (S8 > L_max) { L_max = S8; Nc = lambda + 8; }
|
||||
}
|
||||
*Nc_out = Nc;
|
||||
|
||||
if (L_max <= 0.) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
dp_float -= Nc;
|
||||
L_power = 0;
|
||||
for (k = 0; k < 40; ++k) {
|
||||
register float f = dp_float[k];
|
||||
L_power += f * f;
|
||||
}
|
||||
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Coding of the LTP gain
|
||||
* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
lambda = L_max / L_power * 32768.;
|
||||
for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#endif /* FAST */
|
||||
#endif /* USE_FLOAT_MUL */
|
||||
|
||||
|
||||
/* 4.2.12 */
|
||||
|
||||
static void Long_term_analysis_filtering P6((bc,Nc,dp,d,dpp,e),
|
||||
word bc, /* IN */
|
||||
word Nc, /* IN */
|
||||
register word * dp, /* previous d [-120..-1] IN */
|
||||
register word * d, /* d [0..39] IN */
|
||||
register word * dpp, /* estimate [0..39] OUT */
|
||||
register word * e /* long term res. signal [0..39] OUT */
|
||||
)
|
||||
/*
|
||||
* In this part, we have to decode the bc parameter to compute
|
||||
* the samples of the estimate dpp[0..39]. The decoding of bc needs the
|
||||
* use of table 4.3b. The long term residual signal e[0..39]
|
||||
* is then calculated to be fed to the RPE encoding section.
|
||||
*/
|
||||
{
|
||||
register int k;
|
||||
register longword ltmp;
|
||||
|
||||
# undef STEP
|
||||
# define STEP(BP) \
|
||||
for (k = 0; k <= 39; k++) { \
|
||||
dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \
|
||||
e[k] = (word) GSM_SUB( d[k], dpp[k] ); \
|
||||
}
|
||||
|
||||
switch (bc) {
|
||||
case 0: STEP( 3277 ); break;
|
||||
case 1: STEP( 11469 ); break;
|
||||
case 2: STEP( 21299 ); break;
|
||||
case 3: STEP( 32767 ); break;
|
||||
}
|
||||
}
|
||||
|
||||
void Gsm_Long_Term_Predictor P7((S,d,dp,e,dpp,Nc,bc), /* 4x for 160 samples */
|
||||
|
||||
struct gsm_state * S,
|
||||
|
||||
word * d, /* [0..39] residual signal IN */
|
||||
word * dp, /* [-120..-1] d' IN */
|
||||
|
||||
word * e, /* [0..39] OUT */
|
||||
word * dpp, /* [0..39] OUT */
|
||||
word * Nc, /* correlation lag OUT */
|
||||
word * bc /* gain factor OUT */
|
||||
)
|
||||
{
|
||||
assert( d ); assert( dp ); assert( e );
|
||||
assert( dpp); assert( Nc ); assert( bc );
|
||||
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
if (S->fast)
|
||||
#if defined (LTP_CUT)
|
||||
if (S->ltp_cut)
|
||||
Cut_Fast_Calculation_of_the_LTP_parameters(S,
|
||||
d, dp, bc, Nc);
|
||||
else
|
||||
#endif /* LTP_CUT */
|
||||
Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc );
|
||||
else
|
||||
#endif /* FAST & USE_FLOAT_MUL */
|
||||
#ifdef LTP_CUT
|
||||
if (S->ltp_cut)
|
||||
Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc);
|
||||
else
|
||||
#endif
|
||||
Calculation_of_the_LTP_parameters(d, dp, bc, Nc);
|
||||
|
||||
Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e );
|
||||
}
|
||||
|
||||
/* 4.3.2 */
|
||||
void Gsm_Long_Term_Synthesis_Filtering P5((S,Ncr,bcr,erp,drp),
|
||||
struct gsm_state * S,
|
||||
|
||||
word Ncr,
|
||||
word bcr,
|
||||
register word * erp, /* [0..39] IN */
|
||||
register word * drp /* [-120..-1] IN, [-120..40] OUT */
|
||||
)
|
||||
/*
|
||||
* This procedure uses the bcr and Ncr parameter to realize the
|
||||
* long term synthesis filtering. The decoding of bcr needs
|
||||
* table 4.3b.
|
||||
*/
|
||||
{
|
||||
register longword ltmp; /* for ADD */
|
||||
register int k;
|
||||
word brp, drpp, Nr;
|
||||
|
||||
/* Check the limits of Nr.
|
||||
*/
|
||||
Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr;
|
||||
S->nrp = Nr;
|
||||
assert(Nr >= 40 && Nr <= 120);
|
||||
|
||||
/* Decoding of the LTP gain bcr
|
||||
*/
|
||||
brp = gsm_QLB[ bcr ];
|
||||
|
||||
/* Computation of the reconstructed short term residual
|
||||
* signal drp[0..39]
|
||||
*/
|
||||
assert(brp != MIN_WORD);
|
||||
|
||||
for (k = 0; k <= 39; k++) {
|
||||
drpp = GSM_MULT_R( brp, drp[ k - Nr ] );
|
||||
drp[k] = GSM_ADD( erp[k], drpp );
|
||||
}
|
||||
|
||||
/*
|
||||
* Update of the reconstructed short term residual signal
|
||||
* drp[ -1..-120 ]
|
||||
*/
|
||||
|
||||
for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ];
|
||||
}
|
||||
Vendored
+371
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
#ifdef K6OPT
|
||||
#include "k6opt.h"
|
||||
#endif
|
||||
|
||||
#undef P
|
||||
|
||||
/*
|
||||
* 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION
|
||||
*/
|
||||
|
||||
/* 4.2.4 */
|
||||
|
||||
|
||||
static void Autocorrelation P2((s, L_ACF),
|
||||
word * s, /* [0..159] IN/OUT */
|
||||
longword * L_ACF) /* [0..8] OUT */
|
||||
/*
|
||||
* The goal is to compute the array L_ACF[k]. The signal s[i] must
|
||||
* be scaled in order to avoid an overflow situation.
|
||||
*/
|
||||
{
|
||||
register int k, i;
|
||||
|
||||
word temp, smax, scalauto;
|
||||
|
||||
#ifdef USE_FLOAT_MUL
|
||||
float float_s[160];
|
||||
#endif
|
||||
|
||||
/* Dynamic scaling of the array s[0..159]
|
||||
*/
|
||||
|
||||
/* Search for the maximum.
|
||||
*/
|
||||
#ifndef K6OPT
|
||||
smax = 0;
|
||||
for (k = 0; k <= 159; k++) {
|
||||
temp = GSM_ABS( s[k] );
|
||||
if (temp > smax) smax = temp;
|
||||
}
|
||||
#else
|
||||
{
|
||||
longword lmax;
|
||||
lmax = k6maxmin(s,160,NULL);
|
||||
smax = (lmax > MAX_WORD) ? MAX_WORD : lmax;
|
||||
}
|
||||
#endif
|
||||
/* Computation of the scaling factor.
|
||||
*/
|
||||
if (smax == 0) scalauto = 0;
|
||||
else {
|
||||
assert(smax > 0);
|
||||
scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */
|
||||
}
|
||||
|
||||
/* Scaling of the array s[0...159]
|
||||
*/
|
||||
|
||||
if (scalauto > 0) {
|
||||
# ifndef K6OPT
|
||||
|
||||
# ifdef USE_FLOAT_MUL
|
||||
# define SCALE(n) \
|
||||
case n: for (k = 0; k <= 159; k++) \
|
||||
float_s[k] = (float) \
|
||||
(s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\
|
||||
break;
|
||||
# else
|
||||
# define SCALE(n) \
|
||||
case n: for (k = 0; k <= 159; k++) \
|
||||
s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\
|
||||
break;
|
||||
# endif /* USE_FLOAT_MUL */
|
||||
|
||||
switch (scalauto) {
|
||||
SCALE(1)
|
||||
SCALE(2)
|
||||
SCALE(3)
|
||||
SCALE(4)
|
||||
}
|
||||
# undef SCALE
|
||||
|
||||
# else /* K6OPT */
|
||||
k6vsraw(s,160,scalauto);
|
||||
# endif
|
||||
}
|
||||
# ifdef USE_FLOAT_MUL
|
||||
else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k];
|
||||
# endif
|
||||
|
||||
/* Compute the L_ACF[..].
|
||||
*/
|
||||
#ifndef K6OPT
|
||||
{
|
||||
# ifdef USE_FLOAT_MUL
|
||||
register float * sp = float_s;
|
||||
register float sl = *sp;
|
||||
|
||||
# define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]);
|
||||
# else
|
||||
word * sp = s;
|
||||
word sl = *sp;
|
||||
|
||||
# define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]);
|
||||
# endif
|
||||
|
||||
# define NEXTI sl = *++sp
|
||||
|
||||
|
||||
for (k = 9; k--; L_ACF[k] = 0) ;
|
||||
|
||||
STEP (0);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3); STEP(4);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7);
|
||||
|
||||
for (i = 8; i <= 159; i++) {
|
||||
|
||||
NEXTI;
|
||||
|
||||
STEP(0);
|
||||
STEP(1); STEP(2); STEP(3); STEP(4);
|
||||
STEP(5); STEP(6); STEP(7); STEP(8);
|
||||
}
|
||||
|
||||
for (k = 9; k--; L_ACF[k] <<= 1) ;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
{
|
||||
int k;
|
||||
for (k=0; k<9; k++) {
|
||||
L_ACF[k] = 2*k6iprod(s,s+k,160-k);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Rescaling of the array s[0..159]
|
||||
*/
|
||||
if (scalauto > 0) {
|
||||
assert(scalauto <= 4);
|
||||
#ifndef K6OPT
|
||||
for (k = 160; k--; *s++ <<= scalauto) ;
|
||||
# else /* K6OPT */
|
||||
k6vsllw(s,160,scalauto);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_FLOAT_MUL) && defined(FAST)
|
||||
|
||||
static void Fast_Autocorrelation P2((s, L_ACF),
|
||||
word * s, /* [0..159] IN/OUT */
|
||||
longword * L_ACF) /* [0..8] OUT */
|
||||
{
|
||||
register int k, i;
|
||||
float f_L_ACF[9];
|
||||
float scale;
|
||||
|
||||
float s_f[160];
|
||||
register float *sf = s_f;
|
||||
|
||||
for (i = 0; i < 160; ++i) sf[i] = s[i];
|
||||
for (k = 0; k <= 8; k++) {
|
||||
register float L_temp2 = 0;
|
||||
register float *sfl = sf - k;
|
||||
for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i];
|
||||
f_L_ACF[k] = L_temp2;
|
||||
}
|
||||
scale = MAX_LONGWORD / f_L_ACF[0];
|
||||
|
||||
for (k = 0; k <= 8; k++) {
|
||||
L_ACF[k] = f_L_ACF[k] * scale;
|
||||
}
|
||||
}
|
||||
#endif /* defined (USE_FLOAT_MUL) && defined (FAST) */
|
||||
|
||||
/* 4.2.5 */
|
||||
|
||||
static void Reflection_coefficients P2( (L_ACF, r),
|
||||
longword * L_ACF, /* 0...8 IN */
|
||||
register word * r /* 0...7 OUT */
|
||||
)
|
||||
{
|
||||
register int i, m, n;
|
||||
register word temp;
|
||||
register longword ltmp;
|
||||
word ACF[9]; /* 0..8 */
|
||||
word P[ 9]; /* 0..8 */
|
||||
word K[ 9]; /* 2..8 */
|
||||
|
||||
/* Schur recursion with 16 bits arithmetic.
|
||||
*/
|
||||
|
||||
if (L_ACF[0] == 0) {
|
||||
for (i = 8; i--; *r++ = 0) ;
|
||||
return;
|
||||
}
|
||||
|
||||
assert( L_ACF[0] != 0 );
|
||||
temp = gsm_norm( L_ACF[0] );
|
||||
|
||||
assert(temp >= 0 && temp < 32);
|
||||
|
||||
/* ? overflow ? */
|
||||
for (i = 0; i <= 8; i++) ACF[i] = SASR( L_ACF[i] << temp, 16 );
|
||||
|
||||
/* Initialize array P[..] and K[..] for the recursion.
|
||||
*/
|
||||
|
||||
for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ];
|
||||
for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ];
|
||||
|
||||
/* Compute reflection coefficients
|
||||
*/
|
||||
for (n = 1; n <= 8; n++, r++) {
|
||||
|
||||
temp = P[1];
|
||||
temp = GSM_ABS(temp);
|
||||
if (P[0] < temp) {
|
||||
for (i = n; i <= 8; i++) *r++ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*r = gsm_div( temp, P[0] );
|
||||
|
||||
assert(*r >= 0);
|
||||
if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */
|
||||
assert (*r != MIN_WORD);
|
||||
if (n == 8) return;
|
||||
|
||||
/* Schur recursion
|
||||
*/
|
||||
temp = GSM_MULT_R( P[1], *r );
|
||||
P[0] = GSM_ADD( P[0], temp );
|
||||
|
||||
for (m = 1; m <= 8 - n; m++) {
|
||||
temp = GSM_MULT_R( K[ m ], *r );
|
||||
P[m] = GSM_ADD( P[ m+1 ], temp );
|
||||
|
||||
temp = GSM_MULT_R( P[ m+1 ], *r );
|
||||
K[m] = GSM_ADD( K[ m ], temp );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.6 */
|
||||
|
||||
static void Transformation_to_Log_Area_Ratios P1((r),
|
||||
register word * r /* 0..7 IN/OUT */
|
||||
)
|
||||
/*
|
||||
* The following scaling for r[..] and LAR[..] has been used:
|
||||
*
|
||||
* r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1.
|
||||
* LAR[..] = integer( real_LAR[..] * 16384 );
|
||||
* with -1.625 <= real_LAR <= 1.625
|
||||
*/
|
||||
{
|
||||
register word temp;
|
||||
register int i;
|
||||
|
||||
|
||||
/* Computation of the LAR[0..7] from the r[0..7]
|
||||
*/
|
||||
for (i = 1; i <= 8; i++, r++) {
|
||||
|
||||
temp = *r;
|
||||
temp = GSM_ABS(temp);
|
||||
assert(temp >= 0);
|
||||
|
||||
if (temp < 22118) {
|
||||
temp >>= 1;
|
||||
} else if (temp < 31130) {
|
||||
assert( temp >= 11059 );
|
||||
temp -= 11059;
|
||||
} else {
|
||||
assert( temp >= 26112 );
|
||||
temp -= 26112;
|
||||
temp <<= 2;
|
||||
}
|
||||
|
||||
*r = *r < 0 ? -temp : temp;
|
||||
assert( *r != MIN_WORD );
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.7 */
|
||||
|
||||
static void Quantization_and_coding P1((LAR),
|
||||
register word * LAR /* [0..7] IN/OUT */
|
||||
)
|
||||
{
|
||||
register word temp;
|
||||
longword ltmp;
|
||||
|
||||
|
||||
/* This procedure needs four tables; the following equations
|
||||
* give the optimum scaling for the constants:
|
||||
*
|
||||
* A[0..7] = integer( real_A[0..7] * 1024 )
|
||||
* B[0..7] = integer( real_B[0..7] * 512 )
|
||||
* MAC[0..7] = maximum of the LARc[0..7]
|
||||
* MIC[0..7] = minimum of the LARc[0..7]
|
||||
*/
|
||||
|
||||
# undef STEP
|
||||
# define STEP( A, B, MAC, MIC ) \
|
||||
temp = GSM_MULT( A, *LAR ); \
|
||||
temp = GSM_ADD( temp, B ); \
|
||||
temp = GSM_ADD( temp, 256 ); \
|
||||
temp = SASR( temp, 9 ); \
|
||||
*LAR = temp>MAC ? MAC - MIC : (temp<MIC ? 0 : temp - MIC); \
|
||||
LAR++;
|
||||
|
||||
STEP( 20480, 0, 31, -32 );
|
||||
STEP( 20480, 0, 31, -32 );
|
||||
STEP( 20480, 2048, 15, -16 );
|
||||
STEP( 20480, -2560, 15, -16 );
|
||||
|
||||
STEP( 13964, 94, 7, -8 );
|
||||
STEP( 15360, -1792, 7, -8 );
|
||||
STEP( 8534, -341, 3, -4 );
|
||||
STEP( 9036, -1144, 3, -4 );
|
||||
|
||||
# undef STEP
|
||||
}
|
||||
|
||||
void Gsm_LPC_Analysis P3((S, s,LARc),
|
||||
struct gsm_state *S,
|
||||
word * s, /* 0..159 signals IN/OUT */
|
||||
word * LARc) /* 0..7 LARc's OUT */
|
||||
{
|
||||
longword L_ACF[9];
|
||||
|
||||
#if defined(USE_FLOAT_MUL) && defined(FAST)
|
||||
if (S->fast) Fast_Autocorrelation (s, L_ACF );
|
||||
else
|
||||
#endif
|
||||
Autocorrelation (s, L_ACF );
|
||||
Reflection_coefficients (L_ACF, LARc );
|
||||
Transformation_to_Log_Area_Ratios (LARc);
|
||||
Quantization_and_coding (LARc);
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION
|
||||
*
|
||||
* After A-law to linear conversion (or directly from the
|
||||
* Ato D converter) the following scaling is assumed for
|
||||
* input to the RPE-LTP algorithm:
|
||||
*
|
||||
* in: 0.1.....................12
|
||||
* S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.*
|
||||
*
|
||||
* Where S is the sign bit, v a valid bit, and * a "don't care" bit.
|
||||
* The original signal is called sop[..]
|
||||
*
|
||||
* out: 0.1................... 12
|
||||
* S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0
|
||||
*/
|
||||
|
||||
|
||||
void Gsm_Preprocess P3((S, s, so),
|
||||
struct gsm_state * S,
|
||||
word * s,
|
||||
word * so ) /* [0..159] IN/OUT */
|
||||
{
|
||||
|
||||
word z1 = S->z1;
|
||||
longword L_z2 = S->L_z2;
|
||||
word mp = S->mp;
|
||||
|
||||
word s1;
|
||||
|
||||
|
||||
word SO;
|
||||
|
||||
longword ltmp; /* for ADD */
|
||||
ulongword utmp; /* for L_ADD */
|
||||
|
||||
register int k = 160;
|
||||
|
||||
while (k--) {
|
||||
|
||||
/* 4.2.1 Downscaling of the input signal
|
||||
*/
|
||||
/* SO = SASR( *s, 3 ) << 2;*/
|
||||
SO = SASR( *s, 1 ) & ~3;
|
||||
s++;
|
||||
|
||||
assert (SO >= -0x4000); /* downscaled by */
|
||||
assert (SO <= 0x3FFC); /* previous routine. */
|
||||
|
||||
|
||||
/* 4.2.2 Offset compensation
|
||||
*
|
||||
* This part implements a high-pass filter and requires extended
|
||||
* arithmetic precision for the recursive part of this filter.
|
||||
* The input of this procedure is the array so[0...159] and the
|
||||
* output the array sof[ 0...159 ].
|
||||
*/
|
||||
/* Compute the non-recursive part
|
||||
*/
|
||||
|
||||
s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */
|
||||
z1 = SO;
|
||||
|
||||
assert(s1 != MIN_WORD);
|
||||
|
||||
/* SJB Remark: float might be faster than the mess that follows */
|
||||
|
||||
/* Compute the recursive part
|
||||
*/
|
||||
|
||||
/* Execution of a 31 bv 16 bits multiplication
|
||||
*/
|
||||
{
|
||||
word msp;
|
||||
#ifndef __GNUC__
|
||||
word lsp;
|
||||
#endif
|
||||
longword L_s2;
|
||||
longword L_temp;
|
||||
|
||||
L_s2 = s1;
|
||||
L_s2 <<= 15;
|
||||
#ifndef __GNUC__
|
||||
msp = SASR( L_z2, 15 );
|
||||
lsp = L_z2 & 0x7fff; /* gsm_L_sub(L_z2,(msp<<15)); */
|
||||
|
||||
L_s2 += GSM_MULT_R( lsp, 32735 );
|
||||
L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/
|
||||
L_z2 = GSM_L_ADD( L_temp, L_s2 );
|
||||
/* above does L_z2 = L_z2 * 0x7fd5/0x8000 + L_s2 */
|
||||
#else
|
||||
L_z2 = ((long long)L_z2*32735 + 0x4000)>>15;
|
||||
/* alternate (ansi) version of above line does slightly different rounding:
|
||||
* L_temp = L_z2 >> 9;
|
||||
* L_temp += L_temp >> 5;
|
||||
* L_temp = (++L_temp) >> 1;
|
||||
* L_z2 = L_z2 - L_temp;
|
||||
*/
|
||||
L_z2 = GSM_L_ADD(L_z2,L_s2);
|
||||
#endif
|
||||
/* Compute sof[k] with rounding
|
||||
*/
|
||||
L_temp = GSM_L_ADD( L_z2, 16384 );
|
||||
|
||||
/* 4.2.3 Preemphasis
|
||||
*/
|
||||
|
||||
msp = GSM_MULT_R( mp, -28180 );
|
||||
mp = SASR( L_temp, 15 );
|
||||
*so++ = GSM_ADD( mp, msp );
|
||||
}
|
||||
}
|
||||
|
||||
S->z1 = z1;
|
||||
S->L_z2 = L_z2;
|
||||
S->mp = mp;
|
||||
}
|
||||
Vendored
+491
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
|
||||
/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION
|
||||
*/
|
||||
|
||||
/* 4.2.13 */
|
||||
#ifdef K6OPT
|
||||
#include "k6opt.h"
|
||||
#else
|
||||
static void Weighting_filter P2((e, x),
|
||||
register word * e, /* signal [-5..0.39.44] IN */
|
||||
word * x /* signal [0..39] OUT */
|
||||
)
|
||||
/*
|
||||
* The coefficients of the weighting filter are stored in a table
|
||||
* (see table 4.4). The following scaling is used:
|
||||
*
|
||||
* H[0..10] = integer( real_H[ 0..10] * 8192 );
|
||||
*/
|
||||
{
|
||||
/* word wt[ 50 ]; */
|
||||
|
||||
register longword L_result;
|
||||
register int k /* , i */ ;
|
||||
|
||||
/* Initialization of a temporary working array wt[0...49]
|
||||
*/
|
||||
|
||||
/* for (k = 0; k <= 4; k++) wt[k] = 0;
|
||||
* for (k = 5; k <= 44; k++) wt[k] = *e++;
|
||||
* for (k = 45; k <= 49; k++) wt[k] = 0;
|
||||
*
|
||||
* (e[-5..-1] and e[40..44] are allocated by the caller,
|
||||
* are initially zero and are not written anywhere.)
|
||||
*/
|
||||
e -= 5;
|
||||
|
||||
/* Compute the signal x[0..39]
|
||||
*/
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
L_result = 8192 >> 1;
|
||||
|
||||
/* for (i = 0; i <= 10; i++) {
|
||||
* L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] );
|
||||
* L_result = GSM_L_ADD( L_result, L_temp );
|
||||
* }
|
||||
*/
|
||||
|
||||
#undef STEP
|
||||
#define STEP( i, H ) (e[ k + i ] * (longword)H)
|
||||
|
||||
/* Every one of these multiplications is done twice --
|
||||
* but I don't see an elegant way to optimize this.
|
||||
* Do you?
|
||||
*/
|
||||
|
||||
#ifdef STUPID_COMPILER
|
||||
L_result += STEP( 0, -134 ) ;
|
||||
L_result += STEP( 1, -374 ) ;
|
||||
/* + STEP( 2, 0 ) */
|
||||
L_result += STEP( 3, 2054 ) ;
|
||||
L_result += STEP( 4, 5741 ) ;
|
||||
L_result += STEP( 5, 8192 ) ;
|
||||
L_result += STEP( 6, 5741 ) ;
|
||||
L_result += STEP( 7, 2054 ) ;
|
||||
/* + STEP( 8, 0 ) */
|
||||
L_result += STEP( 9, -374 ) ;
|
||||
L_result += STEP( 10, -134 ) ;
|
||||
#else
|
||||
L_result +=
|
||||
STEP( 0, -134 )
|
||||
+ STEP( 1, -374 )
|
||||
/* + STEP( 2, 0 ) */
|
||||
+ STEP( 3, 2054 )
|
||||
+ STEP( 4, 5741 )
|
||||
+ STEP( 5, 8192 )
|
||||
+ STEP( 6, 5741 )
|
||||
+ STEP( 7, 2054 )
|
||||
/* + STEP( 8, 0 ) */
|
||||
+ STEP( 9, -374 )
|
||||
+ STEP(10, -134 )
|
||||
;
|
||||
#endif
|
||||
|
||||
/* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *)
|
||||
* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *)
|
||||
*
|
||||
* x[k] = SASR( L_result, 16 );
|
||||
*/
|
||||
|
||||
/* 2 adds vs. >>16 => 14, minus one shift to compensate for
|
||||
* those we lost when replacing L_MULT by '*'.
|
||||
*/
|
||||
|
||||
L_result = SASR( L_result, 13 );
|
||||
x[k] = (word) (L_result < MIN_WORD ? MIN_WORD
|
||||
: (L_result > MAX_WORD ? MAX_WORD : L_result));
|
||||
}
|
||||
}
|
||||
#endif /* K6OPT */
|
||||
|
||||
/* 4.2.14 */
|
||||
|
||||
static void RPE_grid_selection P3((x,xM,Mc_out),
|
||||
word * x, /* [0..39] IN */
|
||||
word * xM, /* [0..12] OUT */
|
||||
word * Mc_out /* OUT */
|
||||
)
|
||||
/*
|
||||
* The signal x[0..39] is used to select the RPE grid which is
|
||||
* represented by Mc.
|
||||
*/
|
||||
{
|
||||
/* register word temp1; */
|
||||
register int /* m, */ i;
|
||||
register longword L_result, L_temp;
|
||||
longword EM; /* xxx should be L_EM? */
|
||||
word Mc;
|
||||
|
||||
longword L_common_0_3;
|
||||
|
||||
EM = 0;
|
||||
Mc = 0;
|
||||
|
||||
/* for (m = 0; m <= 3; m++) {
|
||||
* L_result = 0;
|
||||
*
|
||||
*
|
||||
* for (i = 0; i <= 12; i++) {
|
||||
*
|
||||
* temp1 = SASR( x[m + 3*i], 2 );
|
||||
*
|
||||
* assert(temp1 != MIN_WORD);
|
||||
*
|
||||
* L_temp = GSM_L_MULT( temp1, temp1 );
|
||||
* L_result = GSM_L_ADD( L_temp, L_result );
|
||||
* }
|
||||
*
|
||||
* if (L_result > EM) {
|
||||
* Mc = m;
|
||||
* EM = L_result;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
#undef STEP
|
||||
#define STEP( m, i ) L_temp = SASR( x[m + 3 * i], 2 ); \
|
||||
L_result += L_temp * L_temp;
|
||||
|
||||
/* common part of 0 and 3 */
|
||||
|
||||
L_result = 0;
|
||||
STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 );
|
||||
STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 );
|
||||
STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12);
|
||||
L_common_0_3 = L_result;
|
||||
|
||||
/* i = 0 */
|
||||
|
||||
STEP( 0, 0 );
|
||||
L_result <<= 1; /* implicit in L_MULT */
|
||||
EM = L_result;
|
||||
|
||||
/* i = 1 */
|
||||
|
||||
L_result = 0;
|
||||
STEP( 1, 0 );
|
||||
STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 );
|
||||
STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 );
|
||||
STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12);
|
||||
L_result <<= 1;
|
||||
if (L_result > EM) {
|
||||
Mc = 1;
|
||||
EM = L_result;
|
||||
}
|
||||
|
||||
/* i = 2 */
|
||||
|
||||
L_result = 0;
|
||||
STEP( 2, 0 );
|
||||
STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 );
|
||||
STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 );
|
||||
STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12);
|
||||
L_result <<= 1;
|
||||
if (L_result > EM) {
|
||||
Mc = 2;
|
||||
EM = L_result;
|
||||
}
|
||||
|
||||
/* i = 3 */
|
||||
|
||||
L_result = L_common_0_3;
|
||||
STEP( 3, 12 );
|
||||
L_result <<= 1;
|
||||
if (L_result > EM) {
|
||||
Mc = 3;
|
||||
EM = L_result;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
/* Down-sampling by a factor 3 to get the selected xM[0..12]
|
||||
* RPE sequence.
|
||||
*/
|
||||
for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i];
|
||||
*Mc_out = Mc;
|
||||
}
|
||||
|
||||
/* 4.12.15 */
|
||||
|
||||
static void APCM_quantization_xmaxc_to_exp_mant P3((xmaxc,exp_out,mant_out),
|
||||
word xmaxc, /* IN */
|
||||
word * exp_out, /* OUT */
|
||||
word * mant_out ) /* OUT */
|
||||
{
|
||||
word exp, mant;
|
||||
|
||||
/* Compute exponent and mantissa of the decoded version of xmaxc
|
||||
*/
|
||||
|
||||
exp = 0;
|
||||
if (xmaxc > 15) exp = SASR(xmaxc, 3) - 1;
|
||||
mant = xmaxc - (exp << 3);
|
||||
|
||||
if (mant == 0) {
|
||||
exp = -4;
|
||||
mant = 7;
|
||||
}
|
||||
else {
|
||||
while (mant <= 7) {
|
||||
mant = mant << 1 | 1;
|
||||
exp--;
|
||||
}
|
||||
mant -= 8;
|
||||
}
|
||||
|
||||
assert( exp >= -4 && exp <= 6 );
|
||||
assert( mant >= 0 && mant <= 7 );
|
||||
|
||||
*exp_out = exp;
|
||||
*mant_out = mant;
|
||||
}
|
||||
|
||||
static void APCM_quantization P5((xM,xMc,mant_out,exp_out,xmaxc_out),
|
||||
word * xM, /* [0..12] IN */
|
||||
|
||||
word * xMc, /* [0..12] OUT */
|
||||
word * mant_out, /* OUT */
|
||||
word * exp_out, /* OUT */
|
||||
word * xmaxc_out /* OUT */
|
||||
)
|
||||
{
|
||||
int i, itest;
|
||||
|
||||
word xmax, xmaxc, temp, temp1, temp2;
|
||||
word exp, mant;
|
||||
|
||||
|
||||
/* Find the maximum absolute value xmax of xM[0..12].
|
||||
*/
|
||||
|
||||
xmax = 0;
|
||||
for (i = 0; i <= 12; i++) {
|
||||
temp = xM[i];
|
||||
temp = GSM_ABS(temp);
|
||||
if (temp > xmax) xmax = temp;
|
||||
}
|
||||
|
||||
/* Qantizing and coding of xmax to get xmaxc.
|
||||
*/
|
||||
|
||||
exp = 0;
|
||||
temp = SASR( xmax, 9 );
|
||||
itest = 0;
|
||||
|
||||
for (i = 0; i <= 5; i++) {
|
||||
|
||||
itest |= (temp <= 0);
|
||||
temp = SASR( temp, 1 );
|
||||
|
||||
assert(exp <= 5);
|
||||
if (itest == 0) exp++; /* exp = add (exp, 1) */
|
||||
}
|
||||
|
||||
assert(exp <= 6 && exp >= 0);
|
||||
temp = exp + 5;
|
||||
|
||||
assert(temp <= 11 && temp >= 0);
|
||||
xmaxc = gsm_add( SASR(xmax, temp), exp << 3 );
|
||||
|
||||
/* Quantizing and coding of the xM[0..12] RPE sequence
|
||||
* to get the xMc[0..12]
|
||||
*/
|
||||
|
||||
APCM_quantization_xmaxc_to_exp_mant( xmaxc, &exp, &mant );
|
||||
|
||||
/* This computation uses the fact that the decoded version of xmaxc
|
||||
* can be calculated by using the exponent and the mantissa part of
|
||||
* xmaxc (logarithmic table).
|
||||
* So, this method avoids any division and uses only a scaling
|
||||
* of the RPE samples by a function of the exponent. A direct
|
||||
* multiplication by the inverse of the mantissa (NRFAC[0..7]
|
||||
* found in table 4.5) gives the 3 bit coded version xMc[0..12]
|
||||
* of the RPE samples.
|
||||
*/
|
||||
|
||||
|
||||
/* Direct computation of xMc[0..12] using table 4.5
|
||||
*/
|
||||
|
||||
assert( exp <= 4096 && exp >= -4096);
|
||||
assert( mant >= 0 && mant <= 7 );
|
||||
|
||||
temp1 = 6 - exp; /* normalization by the exponent */
|
||||
temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */
|
||||
|
||||
for (i = 0; i <= 12; i++) {
|
||||
|
||||
assert(temp1 >= 0 && temp1 < 16);
|
||||
|
||||
temp = xM[i] << temp1;
|
||||
temp = GSM_MULT( temp, temp2 );
|
||||
temp = SASR(temp, 12);
|
||||
xMc[i] = temp + 4; /* see note below */
|
||||
}
|
||||
|
||||
/* NOTE: This equation is used to make all the xMc[i] positive.
|
||||
*/
|
||||
|
||||
*mant_out = mant;
|
||||
*exp_out = exp;
|
||||
*xmaxc_out = xmaxc;
|
||||
}
|
||||
|
||||
/* 4.2.16 */
|
||||
|
||||
static void APCM_inverse_quantization P4((xMc,mant,exp,xMp),
|
||||
register word * xMc, /* [0..12] IN */
|
||||
word mant,
|
||||
word exp,
|
||||
register word * xMp) /* [0..12] OUT */
|
||||
/*
|
||||
* This part is for decoding the RPE sequence of coded xMc[0..12]
|
||||
* samples to obtain the xMp[0..12] array. Table 4.6 is used to get
|
||||
* the mantissa of xmaxc (FAC[0..7]).
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
word temp, temp1, temp2, temp3;
|
||||
longword ltmp;
|
||||
|
||||
assert( mant >= 0 && mant <= 7 );
|
||||
|
||||
temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */
|
||||
temp2 = gsm_sub( 6, exp ); /* see 4.2-15 for exp */
|
||||
temp3 = gsm_asl( 1, gsm_sub( temp2, 1 ));
|
||||
|
||||
for (i = 13; i--;) {
|
||||
|
||||
assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */
|
||||
|
||||
/* temp = gsm_sub( *xMc++ << 1, 7 ); */
|
||||
temp = (*xMc++ << 1) - 7; /* restore sign */
|
||||
assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */
|
||||
|
||||
temp <<= 12; /* 16 bit signed */
|
||||
temp = GSM_MULT_R( temp1, temp );
|
||||
temp = GSM_ADD( temp, temp3 );
|
||||
*xMp++ = gsm_asr( temp, temp2 );
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.17 */
|
||||
|
||||
static void RPE_grid_positioning P3((Mc,xMp,ep),
|
||||
word Mc, /* grid position IN */
|
||||
register word * xMp, /* [0..12] IN */
|
||||
register word * ep /* [0..39] OUT */
|
||||
)
|
||||
/*
|
||||
* This procedure computes the reconstructed long term residual signal
|
||||
* ep[0..39] for the LTP analysis filter. The inputs are the Mc
|
||||
* which is the grid position selection and the xMp[0..12] decoded
|
||||
* RPE samples which are upsampled by a factor of 3 by inserting zero
|
||||
* values.
|
||||
*/
|
||||
{
|
||||
int i = 13;
|
||||
|
||||
assert(0 <= Mc && Mc <= 3);
|
||||
|
||||
switch (Mc) {
|
||||
case 3: *ep++ = 0;
|
||||
case 2: do {
|
||||
*ep++ = 0;
|
||||
case 1: *ep++ = 0;
|
||||
case 0: *ep++ = *xMp++;
|
||||
} while (--i);
|
||||
}
|
||||
while (++Mc < 4) *ep++ = 0;
|
||||
|
||||
/*
|
||||
|
||||
int i, k;
|
||||
for (k = 0; k <= 39; k++) ep[k] = 0;
|
||||
for (i = 0; i <= 12; i++) {
|
||||
ep[ Mc + (3*i) ] = xMp[i];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* 4.2.18 */
|
||||
|
||||
/* This procedure adds the reconstructed long term residual signal
|
||||
* ep[0..39] to the estimated signal dpp[0..39] from the long term
|
||||
* analysis filter to compute the reconstructed short term residual
|
||||
* signal dp[-40..-1]; also the reconstructed short term residual
|
||||
* array dp[-120..-41] is updated.
|
||||
*/
|
||||
|
||||
#if 0 /* Has been inlined in code.c */
|
||||
void Gsm_Update_of_reconstructed_short_time_residual_signal P3((dpp, ep, dp),
|
||||
word * dpp, /* [0...39] IN */
|
||||
word * ep, /* [0...39] IN */
|
||||
word * dp) /* [-120...-1] IN/OUT */
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0; k <= 79; k++)
|
||||
dp[ -120 + k ] = dp[ -80 + k ];
|
||||
|
||||
for (k = 0; k <= 39; k++)
|
||||
dp[ -40 + k ] = gsm_add( ep[k], dpp[k] );
|
||||
}
|
||||
#endif /* Has been inlined in code.c */
|
||||
|
||||
void Gsm_RPE_Encoding P5((S,e,xmaxc,Mc,xMc),
|
||||
|
||||
struct gsm_state * S,
|
||||
|
||||
word * e, /* -5..-1][0..39][40..44 IN/OUT */
|
||||
word * xmaxc, /* OUT */
|
||||
word * Mc, /* OUT */
|
||||
word * xMc) /* [0..12] OUT */
|
||||
{
|
||||
word x[40];
|
||||
word xM[13], xMp[13];
|
||||
word mant, exp;
|
||||
|
||||
Weighting_filter(e, x);
|
||||
RPE_grid_selection(x, xM, Mc);
|
||||
|
||||
APCM_quantization( xM, xMc, &mant, &exp, xmaxc);
|
||||
APCM_inverse_quantization( xMc, mant, exp, xMp);
|
||||
|
||||
RPE_grid_positioning( *Mc, xMp, e );
|
||||
|
||||
}
|
||||
|
||||
void Gsm_RPE_Decoding P5((S, xmaxcr, Mcr, xMcr, erp),
|
||||
struct gsm_state * S,
|
||||
|
||||
word xmaxcr,
|
||||
word Mcr,
|
||||
word * xMcr, /* [0..12], 3 bits IN */
|
||||
word * erp /* [0..39] OUT */
|
||||
)
|
||||
{
|
||||
word exp, mant;
|
||||
word xMp[ 13 ];
|
||||
|
||||
APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &exp, &mant );
|
||||
APCM_inverse_quantization( xMcr, mant, exp, xMp );
|
||||
RPE_grid_positioning( Mcr, xMp, erp );
|
||||
|
||||
}
|
||||
+452
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "gsm.h"
|
||||
#include "proto.h"
|
||||
#ifdef K6OPT
|
||||
#include "k6opt.h"
|
||||
|
||||
#define Short_term_analysis_filtering Short_term_analysis_filteringx
|
||||
|
||||
#endif
|
||||
/*
|
||||
* SHORT TERM ANALYSIS FILTERING SECTION
|
||||
*/
|
||||
|
||||
/* 4.2.8 */
|
||||
|
||||
static void Decoding_of_the_coded_Log_Area_Ratios P2((LARc,LARpp),
|
||||
word * LARc, /* coded log area ratio [0..7] IN */
|
||||
word * LARpp) /* out: decoded .. */
|
||||
{
|
||||
register word temp1 /* , temp2 */;
|
||||
register long ltmp; /* for GSM_ADD */
|
||||
|
||||
/* This procedure requires for efficient implementation
|
||||
* two tables.
|
||||
*
|
||||
* INVA[1..8] = integer( (32768 * 8) / real_A[1..8])
|
||||
* MIC[1..8] = minimum value of the LARc[1..8]
|
||||
*/
|
||||
|
||||
/* Compute the LARpp[1..8]
|
||||
*/
|
||||
|
||||
/* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) {
|
||||
*
|
||||
* temp1 = GSM_ADD( *LARc, *MIC ) << 10;
|
||||
* temp2 = *B << 1;
|
||||
* temp1 = GSM_SUB( temp1, temp2 );
|
||||
*
|
||||
* assert(*INVA != MIN_WORD);
|
||||
*
|
||||
* temp1 = GSM_MULT_R( *INVA, temp1 );
|
||||
* *LARpp = GSM_ADD( temp1, temp1 );
|
||||
* }
|
||||
*/
|
||||
|
||||
#undef STEP
|
||||
#define STEP( B, MIC, INVA ) \
|
||||
temp1 = (word) GSM_ADD( *LARc++, MIC ) << 10; \
|
||||
temp1 = (word) GSM_SUB( temp1, B << 1 ); \
|
||||
temp1 = (word) GSM_MULT_R( INVA, temp1 ); \
|
||||
*LARpp++ = (word) GSM_ADD( temp1, temp1 );
|
||||
|
||||
STEP( 0, -32, 13107 );
|
||||
STEP( 0, -32, 13107 );
|
||||
STEP( 2048, -16, 13107 );
|
||||
STEP( -2560, -16, 13107 );
|
||||
|
||||
STEP( 94, -8, 19223 );
|
||||
STEP( -1792, -8, 17476 );
|
||||
STEP( -341, -4, 31454 );
|
||||
STEP( -1144, -4, 29708 );
|
||||
|
||||
/* NOTE: the addition of *MIC is used to restore
|
||||
* the sign of *LARc.
|
||||
*/
|
||||
}
|
||||
|
||||
/* 4.2.9 */
|
||||
/* Computation of the quantized reflection coefficients
|
||||
*/
|
||||
|
||||
/* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8]
|
||||
*/
|
||||
|
||||
/*
|
||||
* Within each frame of 160 analyzed speech samples the short term
|
||||
* analysis and synthesis filters operate with four different sets of
|
||||
* coefficients, derived from the previous set of decoded LARs(LARpp(j-1))
|
||||
* and the actual set of decoded LARs (LARpp(j))
|
||||
*
|
||||
* (Initial value: LARpp(j-1)[1..8] = 0.)
|
||||
*/
|
||||
|
||||
static void Coefficients_0_12 P3((LARpp_j_1, LARpp_j, LARp),
|
||||
register word * LARpp_j_1,
|
||||
register word * LARpp_j,
|
||||
register word * LARp)
|
||||
{
|
||||
register int i;
|
||||
register longword ltmp;
|
||||
|
||||
for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) {
|
||||
*LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 ));
|
||||
*LARp = GSM_ADD( *LARp, SASR( *LARpp_j_1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void Coefficients_13_26 P3((LARpp_j_1, LARpp_j, LARp),
|
||||
register word * LARpp_j_1,
|
||||
register word * LARpp_j,
|
||||
register word * LARp)
|
||||
{
|
||||
register int i;
|
||||
register longword ltmp;
|
||||
for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) {
|
||||
*LARp = GSM_ADD( SASR( *LARpp_j_1, 1), SASR( *LARpp_j, 1 ));
|
||||
}
|
||||
}
|
||||
|
||||
static void Coefficients_27_39 P3((LARpp_j_1, LARpp_j, LARp),
|
||||
register word * LARpp_j_1,
|
||||
register word * LARpp_j,
|
||||
register word * LARp)
|
||||
{
|
||||
register int i;
|
||||
register longword ltmp;
|
||||
|
||||
for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) {
|
||||
*LARp = GSM_ADD( SASR( *LARpp_j_1, 2 ), SASR( *LARpp_j, 2 ));
|
||||
*LARp = GSM_ADD( *LARp, SASR( *LARpp_j, 1 ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Coefficients_40_159 P2((LARpp_j, LARp),
|
||||
register word * LARpp_j,
|
||||
register word * LARp)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 1; i <= 8; i++, LARp++, LARpp_j++)
|
||||
*LARp = *LARpp_j;
|
||||
}
|
||||
|
||||
/* 4.2.9.2 */
|
||||
|
||||
static void LARp_to_rp P1((LARp),
|
||||
register word * LARp) /* [0..7] IN/OUT */
|
||||
/*
|
||||
* The input of this procedure is the interpolated LARp[0..7] array.
|
||||
* The reflection coefficients, rp[i], are used in the analysis
|
||||
* filter and in the synthesis filter.
|
||||
*/
|
||||
{
|
||||
register int i;
|
||||
register word temp;
|
||||
register longword ltmp;
|
||||
|
||||
for (i = 1; i <= 8; i++, LARp++) {
|
||||
|
||||
/* temp = GSM_ABS( *LARp );
|
||||
*
|
||||
* if (temp < 11059) temp <<= 1;
|
||||
* else if (temp < 20070) temp += 11059;
|
||||
* else temp = GSM_ADD( temp >> 2, 26112 );
|
||||
*
|
||||
* *LARp = *LARp < 0 ? -temp : temp;
|
||||
*/
|
||||
|
||||
if (*LARp < 0) {
|
||||
temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp);
|
||||
*LARp = - ((temp < 11059) ? temp << 1
|
||||
: ((temp < 20070) ? temp + 11059
|
||||
: GSM_ADD( temp >> 2, 26112 )));
|
||||
} else {
|
||||
temp = *LARp;
|
||||
*LARp = (temp < 11059) ? temp << 1
|
||||
: ((temp < 20070) ? temp + 11059
|
||||
: GSM_ADD( temp >> 2, 26112 ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 4.2.10 */
|
||||
#ifndef Short_term_analysis_filtering
|
||||
|
||||
/* SJB Remark:
|
||||
* I tried 2 MMX versions of this function, neither is significantly
|
||||
* faster than the C version which follows. MMX might be useful if
|
||||
* one were processing 2 input streams in parallel.
|
||||
*/
|
||||
static void Short_term_analysis_filtering P4((u0,rp0,k_n,s),
|
||||
register word * u0,
|
||||
register word * rp0, /* [0..7] IN */
|
||||
register int k_n, /* k_end - k_start */
|
||||
register word * s /* [0..n-1] IN/OUT */
|
||||
)
|
||||
/*
|
||||
* This procedure computes the short term residual signal d[..] to be fed
|
||||
* to the RPE-LTP loop from the s[..] signal and from the local rp[..]
|
||||
* array (quantized reflection coefficients). As the call of this
|
||||
* procedure can be done in many ways (see the interpolation of the LAR
|
||||
* coefficient), it is assumed that the computation begins with index
|
||||
* k_start (for arrays d[..] and s[..]) and stops with index k_end
|
||||
* (k_start and k_end are defined in 4.2.9.1). This procedure also
|
||||
* needs to keep the array u0[0..7] in memory for each call.
|
||||
*/
|
||||
{
|
||||
register word * u_top = u0 + 8;
|
||||
register word * s_top = s + k_n;
|
||||
|
||||
while (s < s_top) {
|
||||
register word *u, *rp ;
|
||||
register longword di, u_out;
|
||||
di = u_out = *s;
|
||||
for (rp=rp0, u=u0; u<u_top;) {
|
||||
register longword ui, rpi;
|
||||
ui = *u;
|
||||
*u++ = (word) u_out;
|
||||
rpi = *rp++;
|
||||
u_out = ui + (((rpi*di)+0x4000)>>15);
|
||||
di = di + (((rpi*ui)+0x4000)>>15);
|
||||
/* make the common case fastest: */
|
||||
if ((u_out == (word)u_out) && (di == (word)di)) continue;
|
||||
/* otherwise do slower fixup (saturation) */
|
||||
if (u_out>MAX_WORD) u_out=MAX_WORD;
|
||||
else if (u_out<MIN_WORD) u_out=MIN_WORD;
|
||||
if (di>MAX_WORD) di=MAX_WORD;
|
||||
else if (di<MIN_WORD) di=MIN_WORD;
|
||||
}
|
||||
*s++ = (word) di;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_FLOAT_MUL) && defined(FAST)
|
||||
|
||||
static void Fast_Short_term_analysis_filtering P4((u,rp,k_n,s),
|
||||
register word * u;
|
||||
register word * rp, /* [0..7] IN */
|
||||
register int k_n, /* k_end - k_start */
|
||||
register word * s /* [0..n-1] IN/OUT */
|
||||
)
|
||||
{
|
||||
register int i;
|
||||
|
||||
float uf[8],
|
||||
rpf[8];
|
||||
|
||||
register float scalef = 3.0517578125e-5;
|
||||
register float sav, di, temp;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
uf[i] = u[i];
|
||||
rpf[i] = rp[i] * scalef;
|
||||
}
|
||||
for (; k_n--; s++) {
|
||||
sav = di = *s;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
register float rpfi = rpf[i];
|
||||
register float ufi = uf[i];
|
||||
|
||||
uf[i] = sav;
|
||||
temp = rpfi * di + ufi;
|
||||
di += rpfi * ufi;
|
||||
sav = temp;
|
||||
}
|
||||
*s = di;
|
||||
}
|
||||
for (i = 0; i < 8; ++i) u[i] = uf[i];
|
||||
}
|
||||
#endif /* ! (defined (USE_FLOAT_MUL) && defined (FAST)) */
|
||||
|
||||
/*
|
||||
* SJB Remark: modified Short_term_synthesis_filtering() below
|
||||
* for significant (abt 35%) speedup of decompression.
|
||||
* (gcc-2.95, k6 cpu)
|
||||
* Please don't change this without benchmarking decompression
|
||||
* to see that you haven't harmed speed.
|
||||
* This function burns most of CPU time for untoasting.
|
||||
* Unfortunately, didn't see any good way to benefit from mmx.
|
||||
*/
|
||||
static void Short_term_synthesis_filtering P5((S,rrp,k,wt,sr),
|
||||
struct gsm_state * S,
|
||||
register word * rrp, /* [0..7] IN */
|
||||
register int k, /* k_end - k_start */
|
||||
register word * wt, /* [0..k-1] IN */
|
||||
register word * sr /* [0..k-1] OUT */
|
||||
)
|
||||
{
|
||||
register word * v = S->v;
|
||||
register int i;
|
||||
register longword sri;
|
||||
|
||||
while (k--) {
|
||||
sri = *wt++;
|
||||
for (i = 8; i--;) {
|
||||
register longword tmp1, tmp2;
|
||||
|
||||
/* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) );
|
||||
*/
|
||||
tmp1 = rrp[i];
|
||||
tmp2 = v[i];
|
||||
|
||||
tmp2 = (( tmp1 * tmp2 + 16384) >> 15) ;
|
||||
/* saturation done below */
|
||||
sri -= tmp2;
|
||||
if (sri != (word)sri) {
|
||||
sri = (sri<0)? MIN_WORD:MAX_WORD;
|
||||
}
|
||||
/* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) );
|
||||
*/
|
||||
|
||||
tmp1 = (( tmp1 * sri + 16384) >> 15) ;
|
||||
/* saturation done below */
|
||||
tmp1 += v[i];
|
||||
if (tmp1 != (word)tmp1) {
|
||||
tmp1 = (tmp1<0)? MIN_WORD:MAX_WORD;
|
||||
}
|
||||
v[i+1] = (word) tmp1;
|
||||
}
|
||||
*sr++ = v[0] = (word) sri;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
|
||||
static void Fast_Short_term_synthesis_filtering P5((S,rrp,k,wt,sr),
|
||||
struct gsm_state * S,
|
||||
register word * rrp, /* [0..7] IN */
|
||||
register int k, /* k_end - k_start */
|
||||
register word * wt, /* [0..k-1] IN */
|
||||
register word * sr /* [0..k-1] OUT */
|
||||
)
|
||||
{
|
||||
register word * v = S->v;
|
||||
register int i;
|
||||
|
||||
float va[9], rrpa[8];
|
||||
register float scalef = 3.0517578125e-5, temp;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
va[i] = v[i];
|
||||
rrpa[i] = (float)rrp[i] * scalef;
|
||||
}
|
||||
while (k--) {
|
||||
register float sri = *wt++;
|
||||
for (i = 8; i--;) {
|
||||
sri -= rrpa[i] * va[i];
|
||||
if (sri < -32768.) sri = -32768.;
|
||||
else if (sri > 32767.) sri = 32767.;
|
||||
|
||||
temp = va[i] + rrpa[i] * sri;
|
||||
if (temp < -32768.) temp = -32768.;
|
||||
else if (temp > 32767.) temp = 32767.;
|
||||
va[i+1] = temp;
|
||||
}
|
||||
*sr++ = va[0] = sri;
|
||||
}
|
||||
for (i = 0; i < 9; ++i) v[i] = va[i];
|
||||
}
|
||||
|
||||
#endif /* defined(FAST) && defined(USE_FLOAT_MUL) */
|
||||
|
||||
void Gsm_Short_Term_Analysis_Filter P3((S,LARc,s),
|
||||
|
||||
struct gsm_state * S,
|
||||
|
||||
word * LARc, /* coded log area ratio [0..7] IN */
|
||||
word * s /* signal [0..159] IN/OUT */
|
||||
)
|
||||
{
|
||||
word * LARpp_j = S->LARpp[ S->j ];
|
||||
word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ];
|
||||
|
||||
word LARp[8];
|
||||
#undef FILTER
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
# define FILTER (* (S->fast \
|
||||
? Fast_Short_term_analysis_filtering \
|
||||
: Short_term_analysis_filtering ))
|
||||
|
||||
#else
|
||||
# define FILTER Short_term_analysis_filtering
|
||||
#endif
|
||||
|
||||
Decoding_of_the_coded_Log_Area_Ratios( LARc, LARpp_j );
|
||||
|
||||
Coefficients_0_12( LARpp_j_1, LARpp_j, LARp );
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S->u, LARp, 13, s);
|
||||
|
||||
Coefficients_13_26( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S->u, LARp, 14, s + 13);
|
||||
|
||||
Coefficients_27_39( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S->u, LARp, 13, s + 27);
|
||||
|
||||
Coefficients_40_159( LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S->u, LARp, 120, s + 40);
|
||||
|
||||
}
|
||||
|
||||
void Gsm_Short_Term_Synthesis_Filter P4((S, LARcr, wt, s),
|
||||
struct gsm_state * S,
|
||||
|
||||
word * LARcr, /* received log area ratios [0..7] IN */
|
||||
word * wt, /* received d [0..159] IN */
|
||||
|
||||
word * s /* signal s [0..159] OUT */
|
||||
)
|
||||
{
|
||||
word * LARpp_j = S->LARpp[ S->j ];
|
||||
word * LARpp_j_1 = S->LARpp[ S->j ^=1 ];
|
||||
|
||||
word LARp[8];
|
||||
|
||||
#undef FILTER
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
|
||||
# define FILTER (* (S->fast \
|
||||
? Fast_Short_term_synthesis_filtering \
|
||||
: Short_term_synthesis_filtering ))
|
||||
#else
|
||||
# define FILTER Short_term_synthesis_filtering
|
||||
#endif
|
||||
|
||||
Decoding_of_the_coded_Log_Area_Ratios( LARcr, LARpp_j );
|
||||
|
||||
Coefficients_0_12( LARpp_j_1, LARpp_j, LARp );
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 13, wt, s );
|
||||
|
||||
Coefficients_13_26( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 14, wt + 13, s + 13 );
|
||||
|
||||
Coefficients_27_39( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 13, wt + 27, s + 27 );
|
||||
|
||||
Coefficients_40_159( LARpp_j, LARp );
|
||||
LARp_to_rp( LARp );
|
||||
FILTER(S, LARp, 120, wt + 40, s + 40);
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/* Most of these tables are inlined at their point of use.
|
||||
*/
|
||||
|
||||
/* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP
|
||||
* CODER AND DECODER
|
||||
*
|
||||
* (Most of them inlined, so watch out.)
|
||||
*/
|
||||
|
||||
#define GSM_TABLE_C
|
||||
#include "private.h"
|
||||
#include "gsm.h"
|
||||
|
||||
/* Table 4.1 Quantization of the Log.-Area Ratios
|
||||
*/
|
||||
/* i 1 2 3 4 5 6 7 8 */
|
||||
word gsm_A[8] = {20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036};
|
||||
word gsm_B[8] = { 0, 0, 2048, -2560, 94, -1792, -341, -1144};
|
||||
word gsm_MIC[8] = { -32, -32, -16, -16, -8, -8, -4, -4 };
|
||||
word gsm_MAC[8] = { 31, 31, 15, 15, 7, 7, 3, 3 };
|
||||
|
||||
|
||||
/* Table 4.2 Tabulation of 1/A[1..8]
|
||||
*/
|
||||
word gsm_INVA[8]={ 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 };
|
||||
|
||||
|
||||
/* Table 4.3a Decision level of the LTP gain quantizer
|
||||
*/
|
||||
/* bc 0 1 2 3 */
|
||||
word gsm_DLB[4] = { 6554, 16384, 26214, 32767 };
|
||||
|
||||
|
||||
/* Table 4.3b Quantization levels of the LTP gain quantizer
|
||||
*/
|
||||
/* bc 0 1 2 3 */
|
||||
word gsm_QLB[4] = { 3277, 11469, 21299, 32767 };
|
||||
|
||||
|
||||
/* Table 4.4 Coefficients of the weighting filter
|
||||
*/
|
||||
/* i 0 1 2 3 4 5 6 7 8 9 10 */
|
||||
word gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 };
|
||||
|
||||
|
||||
/* Table 4.5 Normalized inverse mantissa used to compute xM/xmax
|
||||
*/
|
||||
/* i 0 1 2 3 4 5 6 7 */
|
||||
word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 };
|
||||
|
||||
|
||||
/* Table 4.6 Normalized direct mantissa used to compute xM/xmax
|
||||
*/
|
||||
/* i 0 1 2 3 4 5 6 7 */
|
||||
word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 };
|
||||
Vendored
+1384
File diff suppressed because it is too large
Load Diff
+2010
File diff suppressed because it is too large
Load Diff
+270
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* iaxclient: a cross-platform IAX softphone library
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2003-2006, Horizon Wimba, Inc.
|
||||
* Copyright (C) 2007, Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
* Michael Van Donselaar <mvand@vandonselaar.org>
|
||||
* Shawn Lawrence <shawn.lawrence@terracecomm.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License.
|
||||
*/
|
||||
#ifndef _iaxclient_lib_h
|
||||
#define _iaxclient_lib_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* This is the internal include file for IAXCLIENT -- externally
|
||||
* accessible APIs should be declared in iaxclient.h */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#include "winpoop.h"
|
||||
#if !defined(_WIN32_WCE)
|
||||
#include <process.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
// To access to check_ff function
|
||||
#include "codec_ffmpeg.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "spandsp/plc.h"
|
||||
|
||||
|
||||
|
||||
/* os-dependent macros, etc */
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#define THREAD HANDLE
|
||||
#define THREADID unsigned
|
||||
#define THREADCREATE(func, args, thread, id) \
|
||||
(thread = (HANDLE)_beginthreadex(NULL, 0, func, (PVOID)args, 0, &id))
|
||||
#define THREADCREATE_ERROR NULL
|
||||
#define THREADFUNCDECL(func) unsigned __stdcall func(PVOID args)
|
||||
#define THREADFUNCRET(r) int r = 0
|
||||
#define THREADJOIN(t)
|
||||
/* causes deadlock with wx GUI on MSW */
|
||||
/* #define THREADJOIN(t) WaitForSingleObject(t, INFINITE) */
|
||||
#ifndef _WIN32_WINNT
|
||||
extern WINBASEAPI BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
|
||||
#endif
|
||||
#define MUTEX CRITICAL_SECTION
|
||||
#define MUTEXINIT(m) InitializeCriticalSection(m)
|
||||
#define MUTEXLOCK(m) EnterCriticalSection(m)
|
||||
#define MUTEXTRYLOCK(m) (!TryEnterCriticalSection(m))
|
||||
#define MUTEXUNLOCK(m) LeaveCriticalSection(m)
|
||||
#define MUTEXDESTROY(m) DeleteCriticalSection(m)
|
||||
|
||||
#else
|
||||
#define THREAD pthread_t
|
||||
#define THREADID unsigned /* unused for Posix Threads */
|
||||
#define THREADCREATE(func, args, thread, id) \
|
||||
pthread_create(&thread, NULL, func, args)
|
||||
#define THREADCREATE_ERROR -1
|
||||
#define THREADFUNCDECL(func) void * func(void *args)
|
||||
#define THREADFUNCRET(r) void * r = 0
|
||||
#define THREADJOIN(t) pthread_join(t, 0)
|
||||
#define MUTEX pthread_mutex_t
|
||||
#define MUTEXINIT(m) pthread_mutex_init(m, NULL) //TODO: check error
|
||||
#define MUTEXLOCK(m) pthread_mutex_lock(m)
|
||||
#define MUTEXTRYLOCK(m) pthread_mutex_trylock(m)
|
||||
#define MUTEXUNLOCK(m) pthread_mutex_unlock(m)
|
||||
#define MUTEXDESTROY(m) pthread_mutex_destroy(m)
|
||||
#endif
|
||||
|
||||
#ifdef MACOSX
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/thread_policy.h>
|
||||
#include <sched.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#define MAXARGS 10
|
||||
#define MAXARG 256
|
||||
#define MAX_SESSIONS 4
|
||||
#define OUT_INTERVAL 20
|
||||
|
||||
/* millisecond interval to time out calls */
|
||||
#define IAXC_CALL_TIMEOUT 30000
|
||||
|
||||
|
||||
void os_init(void);
|
||||
void iaxci_usermsg(int type, const char *fmt, ...);
|
||||
void iaxci_do_levels_callback(float input, float output);
|
||||
void iaxci_do_audio_callback(int callNo, unsigned int ts, int remote,
|
||||
int encoded, int format, int size, unsigned char *data);
|
||||
|
||||
#include "iaxclient.h"
|
||||
|
||||
struct iaxc_audio_driver {
|
||||
/* data */
|
||||
char *name; /* driver name */
|
||||
struct iaxc_audio_device *devices; /* list of devices */
|
||||
int nDevices; /* count of devices */
|
||||
void *priv; /* pointer to private data */
|
||||
|
||||
/* methods */
|
||||
int (*initialize)(struct iaxc_audio_driver *d, int sample_rate);
|
||||
int (*destroy)(struct iaxc_audio_driver *d); /* free resources */
|
||||
int (*select_devices)(struct iaxc_audio_driver *d, int input, int output, int ring);
|
||||
int (*selected_devices)(struct iaxc_audio_driver *d, int *input, int *output, int *ring);
|
||||
|
||||
/*
|
||||
* select_ring ?
|
||||
* set_latency
|
||||
*/
|
||||
|
||||
int (*start)(struct iaxc_audio_driver *d);
|
||||
int (*stop)(struct iaxc_audio_driver *d);
|
||||
int (*output)(struct iaxc_audio_driver *d, void *samples, int nSamples);
|
||||
int (*input)(struct iaxc_audio_driver *d, void *samples, int *nSamples);
|
||||
|
||||
/* levels */
|
||||
float (*input_level_get)(struct iaxc_audio_driver *d);
|
||||
float (*output_level_get)(struct iaxc_audio_driver *d);
|
||||
int (*input_level_set)(struct iaxc_audio_driver *d, float level);
|
||||
int (*output_level_set)(struct iaxc_audio_driver *d, float level);
|
||||
|
||||
/* sounds */
|
||||
int (*play_sound)(struct iaxc_sound *s, int ring);
|
||||
int (*stop_sound)(int id);
|
||||
|
||||
/* mic boost */
|
||||
int (*mic_boost_get)(struct iaxc_audio_driver *d ) ;
|
||||
int (*mic_boost_set)(struct iaxc_audio_driver *d, int enable);
|
||||
};
|
||||
|
||||
struct iaxc_audio_codec {
|
||||
char name[256];
|
||||
int format;
|
||||
int minimum_frame_size;
|
||||
void *encstate;
|
||||
void *decstate;
|
||||
int (*encode) ( struct iaxc_audio_codec *codec, int *inlen, short *in, int *outlen, unsigned char *out );
|
||||
int (*decode) ( struct iaxc_audio_codec *codec, int *inlen, unsigned char *in, int *outlen, short *out );
|
||||
void (*destroy) ( struct iaxc_audio_codec *codec);
|
||||
};
|
||||
|
||||
#define MAX_TRUNK_LEN (1<<16)
|
||||
#define MAX_NO_SLICES 32
|
||||
|
||||
struct slice_set_t
|
||||
{
|
||||
int num_slices;
|
||||
int key_frame;
|
||||
int size[MAX_NO_SLICES];
|
||||
char data[MAX_NO_SLICES][MAX_TRUNK_LEN];
|
||||
};
|
||||
|
||||
struct iaxc_video_codec {
|
||||
char name[256];
|
||||
int format;
|
||||
int width;
|
||||
int height;
|
||||
int framerate;
|
||||
int bitrate;
|
||||
int fragsize;
|
||||
int params_changed;
|
||||
void *encstate;
|
||||
void *decstate;
|
||||
struct iaxc_video_stats video_stats;
|
||||
int (*encode)(struct iaxc_video_codec * codec, int inlen,
|
||||
const char * in, struct slice_set_t * out);
|
||||
int (*decode)(struct iaxc_video_codec * codec, int inlen,
|
||||
const char * in, int * outlen, char * out);
|
||||
void (*destroy)(struct iaxc_video_codec * codec);
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct iaxc_call {
|
||||
/* to be replaced with codec-structures, with codec-private data */
|
||||
struct iaxc_audio_codec *encoder;
|
||||
struct iaxc_audio_codec *decoder;
|
||||
struct iaxc_video_codec *vencoder;
|
||||
struct iaxc_video_codec *vdecoder;
|
||||
int vformat;
|
||||
|
||||
/* the "state" of this call */
|
||||
int state;
|
||||
char remote[IAXC_EVENT_BUFSIZ];
|
||||
char remote_name[IAXC_EVENT_BUFSIZ];
|
||||
char local[IAXC_EVENT_BUFSIZ];
|
||||
char local_context[IAXC_EVENT_BUFSIZ];
|
||||
|
||||
/* Outbound CallerID */
|
||||
char callerid_name[IAXC_EVENT_BUFSIZ];
|
||||
char callerid_number[IAXC_EVENT_BUFSIZ];
|
||||
|
||||
/* reset whenever we receive packets from remote */
|
||||
struct timeval last_activity;
|
||||
struct timeval last_ping;
|
||||
|
||||
/* our negotiated format */
|
||||
int format;
|
||||
|
||||
/* we've sent a silent frame since the last audio frame */
|
||||
int tx_silent;
|
||||
|
||||
struct iax_session *session;
|
||||
};
|
||||
|
||||
#include "audio_encode.h"
|
||||
|
||||
#ifdef AUDIO_PA
|
||||
#include "audio_portaudio.h"
|
||||
#endif
|
||||
|
||||
#include "audio_file.h"
|
||||
|
||||
#ifdef AUDIO_OPENAL
|
||||
#include "audio_openal.h"
|
||||
#endif
|
||||
|
||||
extern int iaxci_audio_output_mode;
|
||||
|
||||
int iaxci_post_event_callback(iaxc_event e);
|
||||
|
||||
/* post an event to the application */
|
||||
void iaxci_post_event(iaxc_event e);
|
||||
|
||||
/* parameters for callback */
|
||||
extern void * post_event_handle;
|
||||
extern int post_event_id;
|
||||
|
||||
/* Priority boost support */
|
||||
extern int iaxci_prioboostbegin(void);
|
||||
extern int iaxci_prioboostend(void);
|
||||
|
||||
long iaxci_usecdiff(struct timeval *t0, struct timeval *t1);
|
||||
long iaxci_msecdiff(struct timeval *t0, struct timeval *t1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
+416
@@ -0,0 +1,416 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
+482
@@ -0,0 +1,482 @@
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
libiax
|
||||
======
|
||||
|
||||
version 0.2.3:
|
||||
* Allow password to be passed in connect
|
||||
|
||||
version 0.2.2 (Nov 13th, 2001):
|
||||
* HTML Unlink requests
|
||||
* HTML Reject link requests
|
||||
* Text frames
|
||||
|
||||
version 0.2.1 (Oct 20th, 2001):
|
||||
* More space for challenge in IAX
|
||||
* Fixed strncpy security bug
|
||||
* Accept larger packets
|
||||
* Handle out of order packets better
|
||||
* Implemented send_url
|
||||
* Added an iax-config script :-)
|
||||
|
||||
version 0.2.0 (Oct 10th, 2001):
|
||||
* Initial Public Release
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script). Here is a another example:
|
||||
|
||||
/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
|
||||
configuration-related scripts to be executed by `/bin/bash'.
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
SUBDIRS = src
|
||||
|
||||
bin_SCRIPTS=iax-config
|
||||
BUILT_SCOURCES=iax-config
|
||||
EXTRA_DIST=iax.spec libiax2.vcproj
|
||||
iax-config: iax-config.in
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
libiax
|
||||
======
|
||||
|
||||
0.2.3:
|
||||
|
||||
0.2.2:
|
||||
|
||||
0.2.1:
|
||||
|
||||
0.2.0 (Oct 10th, 2001):
|
||||
Initial Release. Hooray! Rejoice! :)
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
libiax: An implementation of the Inter-Asterisk eXchange protocol distributed
|
||||
under the terms of the GNU Lesser General Public License
|
||||
|
||||
Written by Mark Spencer <markster@linux-support.net>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
echo If this fails you probably need to download the latest
|
||||
echo libtool,aclocal,autoconf and automake
|
||||
libtoolize --force
|
||||
aclocal --force
|
||||
autoconf -f
|
||||
automake -acf
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
echo configuring automake
|
||||
./bootstrap.sh
|
||||
echo configuring libiax2
|
||||
./configure --enable-newjb
|
||||
echo building libiax2
|
||||
make
|
||||
echo
|
||||
echo
|
||||
echo '##################################################################'
|
||||
echo '# #'
|
||||
echo '# If all is well, enter "make install" to complete installation. #'
|
||||
echo '# #'
|
||||
echo '##################################################################'
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
dnl Yo Yo Yo
|
||||
AC_INIT(src/iax.c)
|
||||
AM_INIT_AUTOMAKE([iax], [0.2.3])
|
||||
|
||||
|
||||
dnl Check for various goodies
|
||||
AC_PROG_CC
|
||||
AM_PROG_LIBTOOL
|
||||
dnl LIBTOOL="$LIBTOOL --silent"
|
||||
AC_PROG_INSTALL
|
||||
|
||||
dnl Check for libraries
|
||||
dnl None available
|
||||
|
||||
dnl Check header files
|
||||
AC_HEADER_STDC
|
||||
|
||||
AC_CHECK_FUNCS(gettimeofday)
|
||||
|
||||
AC_SUBST(LIBS)
|
||||
|
||||
AC_ARG_ENABLE(snomhack, [ --enable-snomhack Use slower memset for SNOM phoneem ],,enable_snomhack=no)
|
||||
AC_ARG_ENABLE(extreme_debug, [ --enable-extreme-debug Compile with extreme debugging code enabled ],,enable_extreme_debug=no)
|
||||
if test "$enable_snomhack" = yes ; then
|
||||
AC_DEFINE(SNOM_HACK)
|
||||
fi
|
||||
|
||||
if test "$enable_extreme_debug" = yes ; then
|
||||
AC_DEFINE(EXTREME_DEBUG)
|
||||
fi
|
||||
|
||||
AC_SUBST(IAX_VERSION)
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
src/Makefile
|
||||
iax.spec
|
||||
iax-config],[case "$CONFIG_FILES" in
|
||||
*iax-config*)chmod +x iax-config;;
|
||||
esac])
|
||||
+530
@@ -0,0 +1,530 @@
|
||||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2005-07-09.11
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by `PROGRAMS ARGS'.
|
||||
object Object file output by `PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputing dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
"$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the `deleted header file' problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the `:'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like `#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr '
|
||||
' ' ' >> $depfile
|
||||
echo >> $depfile
|
||||
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> $depfile
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts `$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
|
||||
tmpdepfile="$stripped.u"
|
||||
if test "$libtool" = yes; then
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test -f "$tmpdepfile"; then :
|
||||
else
|
||||
stripped=`echo "$stripped" | sed 's,^.*/,,'`
|
||||
tmpdepfile="$stripped.u"
|
||||
fi
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
if test -f "$tmpdepfile"; then
|
||||
outname="$stripped.o"
|
||||
# Each line is of the form `foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler understands `-MD -MF file'. However on
|
||||
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want:
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using \ :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
|
||||
sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in `foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mecanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
# That's a tab and a space in the [].
|
||||
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for `:'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no
|
||||
for arg in "$@"; do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix="`echo $object | sed 's/^.*\././'`"
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' '
|
||||
' | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o,
|
||||
# because we must use -o when running libtool.
|
||||
"$@" || exit $?
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
|
||||
echo " " >> "$depfile"
|
||||
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Run this to generate a new configure script and such :)
|
||||
#
|
||||
# -- Rob
|
||||
#
|
||||
|
||||
|
||||
(libtoolize --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo;
|
||||
echo "You must have libtool installed to compile libiax";
|
||||
echo;
|
||||
exit;
|
||||
}
|
||||
|
||||
libtoolize --copy --force
|
||||
aclocal
|
||||
autoconf
|
||||
automake
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
#!/bin/sh
|
||||
iax_libs="-L/usr/lib -liax"
|
||||
iax_cflags=""
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
exec_prefix_set=no
|
||||
|
||||
usage="\
|
||||
Usage: iax-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo "${usage}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
|
||||
*) optarg= ;;
|
||||
esac
|
||||
|
||||
case $1 in
|
||||
--prefix=*)
|
||||
prefix=$optarg
|
||||
if test $exec_prefix_set = no ; then
|
||||
exec_prefix=$optarg
|
||||
fi
|
||||
;;
|
||||
--prefix)
|
||||
echo $prefix
|
||||
;;
|
||||
--exec-prefix=*)
|
||||
exec_prefix=$optarg
|
||||
exec_prefix_set=yes
|
||||
;;
|
||||
--exec-prefix)
|
||||
echo $exec_prefix
|
||||
;;
|
||||
--version)
|
||||
echo @VERSION@
|
||||
;;
|
||||
--cflags)
|
||||
# if test ${prefix}/include/iax != /usr/include/iax ; then
|
||||
includes=-I${prefix}/include/iax
|
||||
for i in $iax_cflags ; do
|
||||
if test $i = -I${prefix}/include ; then
|
||||
includes=""
|
||||
fi
|
||||
done
|
||||
# fi
|
||||
echo $includes $iax_cflags
|
||||
;;
|
||||
--libs)
|
||||
my_iax_libs=
|
||||
libdirs=-L${exec_prefix}/lib
|
||||
for i in $iax_libs ; do
|
||||
if test $i != -L${exec_prefix}/lib ; then
|
||||
if test -z "$my_iax_libs" ; then
|
||||
my_iax_libs="$i"
|
||||
else
|
||||
my_iax_libs="$my_iax_libs $i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo $libdirs $my_iax_libs
|
||||
;;
|
||||
*)
|
||||
echo "${usage}" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
%define name @PACKAGE@
|
||||
%define version @VERSION@
|
||||
%define release 1
|
||||
%define prefix /usr
|
||||
|
||||
Summary: IAX (Inter Asterisk eXchange) Library
|
||||
Name: %{name}
|
||||
Version: %{version}
|
||||
Release: %{release}
|
||||
Copyright: LGPL
|
||||
Group: Development/Libraries
|
||||
Source: %{name}-%{version}.tar.gz
|
||||
URL: http://www.linux-support.net/
|
||||
Distribution: RedHat Linux
|
||||
Vendor: Linux Support Services
|
||||
Packager: Rob Flynn <rob@linux-support.net>
|
||||
BuildRoot: /var/tmp/%{name}-%{version}-root
|
||||
|
||||
%description
|
||||
Inter Asterisk eXchange, lovingly called IAX (pronounced: eeks), is the protocol used by the Asterisk PBX
|
||||
system for inter-asterisk-communication. Other applications may use libiax to communicate with each other
|
||||
and other asterisk servers. IAX is a high performance, feature rich protocol unrelated
|
||||
to SIP or H.323. Its single-socket design allows it to interoperate with NAT and PAT
|
||||
masquerade firewalls. It supports internationalization, remote dialplans,
|
||||
and voice, HTML, image, DTMF, and video content. For more information see
|
||||
http://www.gnophone.com.
|
||||
|
||||
%package devel
|
||||
Summary: IAX (Inter Asterisk eXchange) Development Package
|
||||
Group: Development/Libraries
|
||||
Requires: iax
|
||||
|
||||
%description devel
|
||||
Inter Asterisk eXchange, lovingly called IAX (pronounced: eeks), is the protocol used by the Asterisk PBX
|
||||
system for inter-asterisk-communication. Other applications may use libiax to communicate with each other
|
||||
and other asterisk servers. IAX is a high performance, feature rich protocol unrelated
|
||||
to SIP or H.323. Its single-socket design allows it to interoperate with NAT and PAT
|
||||
masquerade firewalls. It supports internationalization, remote dialplans,
|
||||
and voice, HTML, image, DTMF, and video content. For more information see
|
||||
http://www.gnophone.com.
|
||||
|
||||
This package contains all of the development files that you will need in order to compile IAX applications.
|
||||
|
||||
%prep
|
||||
|
||||
%setup
|
||||
|
||||
%build
|
||||
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} --enable-autoupdate
|
||||
make
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make prefix=$RPM_BUILD_ROOT%{prefix} install-strip
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc NEWS COPYING AUTHORS README
|
||||
%{prefix}/lib
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root)
|
||||
%{prefix}/include/iax
|
||||
%{prefix}/bin/*
|
||||
|
||||
%clean
|
||||
rm -r $RPM_BUILD_ROOT
|
||||
|
||||
%changelog
|
||||
* Tue Nov 13 2001 Rob Flynn <rob@linux-support.net> (0.2.2 release)
|
||||
- HTML Unlink requests
|
||||
- HTML Reject link requests
|
||||
- Text frames
|
||||
|
||||
* Sat Oct 20 2001 Rob Flynn <rob@linux-support.net> (0.2.1 release)
|
||||
- More space for challenge in IAX
|
||||
- Fixed strncpy security bug
|
||||
- Accept larger packets
|
||||
- Handle out of order packets better
|
||||
- Implemented send_url
|
||||
- Added an iax-config script :-)
|
||||
|
||||
* Wed Oct 10 2001 Rob Flynn <rob@linux-support.net> (0.2.0 release)
|
||||
- Initial public release
|
||||
|
||||
%post
|
||||
|
||||
%preun
|
||||
|
||||
%postun
|
||||
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2005-05-14.22
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=
|
||||
chgrpcmd=
|
||||
stripcmd=
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dstarg=
|
||||
no_target_directory=
|
||||
|
||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
-c (ignored)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test -n "$1"; do
|
||||
case $1 in
|
||||
-c) shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t) dstarg=$2
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-T) no_target_directory=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
*) # When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
test -n "$dir_arg$dstarg" && break
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dstarg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dstarg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dstarg=$arg
|
||||
done
|
||||
break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test -z "$1"; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src ;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
src=
|
||||
|
||||
if test -d "$dst"; then
|
||||
mkdircmd=:
|
||||
chmodcmd=
|
||||
else
|
||||
mkdircmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dstarg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dstarg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst ;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dstarg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst/`basename "$src"`
|
||||
fi
|
||||
fi
|
||||
|
||||
# This sed command emulates the dirname command.
|
||||
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if test ! -d "$dstdir"; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
shift
|
||||
IFS=$oIFS
|
||||
|
||||
pathcomp=
|
||||
|
||||
while test $# -ne 0 ; do
|
||||
pathcomp=$pathcomp$1
|
||||
shift
|
||||
if test ! -d "$pathcomp"; then
|
||||
$mkdirprog "$pathcomp"
|
||||
# mkdir can fail with a `File exist' error in case several
|
||||
# install-sh are creating the directory concurrently. This
|
||||
# is OK.
|
||||
test -d "$pathcomp" || exit
|
||||
fi
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
$doit $mkdircmd "$dst" \
|
||||
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
|
||||
|
||||
else
|
||||
dstfile=`basename "$dst"`
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
$doit $cpprog "$src" "$dsttmp" &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| {
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
if test -f "$dstdir/$dstfile"; then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
}
|
||||
}
|
||||
fi || { (exit 1); exit 1; }
|
||||
done
|
||||
|
||||
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||
{
|
||||
(exit 0); exit 0
|
||||
}
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="libiax2"
|
||||
ProjectGUID="{5CC054B7-6DAA-46BF-9A08-3B33B83E8D3E}"
|
||||
RootNamespace="libiax2"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
InlineFunctionExpansion="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LIBIAX;DEBUG_SUPPORT;_CRT_SECURE_NO_DEPRECATE;NEWJB"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LIBIAX"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\iax.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\iax2-parser.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\jitterbuf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\md5.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\answer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\busy.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\dialtone.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\frame.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\iax-client.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\iax.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\iax2-parser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\iax2.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\jitterbuf.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\md5.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\miniphone.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\options.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ring10.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ringtone.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\winpoop.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
+360
@@ -0,0 +1,360 @@
|
||||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2005-06-08.21
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case "$1" in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program).
|
||||
case "$1" in
|
||||
lex|yacc)
|
||||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
tar)
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case "$1" in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case "$f" in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
||||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison|yacc)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f y.tab.h ]; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if [ ! -f y.tab.c ]; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex|flex)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f lex.yy.c ]; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
||||
fi
|
||||
if [ -f "$file" ]; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# The file to touch is that specified with -o ...
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
|
||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
fi
|
||||
# If the file does not exist, the user really needs makeinfo;
|
||||
# let's fail without touching anything.
|
||||
test -f $file || exit 1
|
||||
touch $file
|
||||
;;
|
||||
|
||||
tar)
|
||||
shift
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case "$firstarg" in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case "$firstarg" in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
#! /bin/sh
|
||||
# mkinstalldirs --- make directory hierarchy
|
||||
|
||||
scriptversion=2005-06-29.22
|
||||
|
||||
# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-05-16
|
||||
# Public domain.
|
||||
#
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
errstatus=0
|
||||
dirmode=
|
||||
|
||||
usage="\
|
||||
Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
|
||||
|
||||
Create each directory DIR (with mode MODE, if specified), including all
|
||||
leading file name components.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>."
|
||||
|
||||
# process command line arguments
|
||||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
-h | --help | --h*) # -h for help
|
||||
echo "$usage"
|
||||
exit $?
|
||||
;;
|
||||
-m) # -m PERM arg
|
||||
shift
|
||||
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
|
||||
dirmode=$1
|
||||
shift
|
||||
;;
|
||||
--version)
|
||||
echo "$0 $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
--) # stop option processing
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*) # unknown option
|
||||
echo "$usage" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
*) # first non-opt arg
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
for file
|
||||
do
|
||||
if test -d "$file"; then
|
||||
shift
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
case $# in
|
||||
0) exit 0 ;;
|
||||
esac
|
||||
|
||||
# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
|
||||
# mkdir -p a/c at the same time, both will detect that a is missing,
|
||||
# one will create a, then the other will try to create a and die with
|
||||
# a "File exists" error. This is a problem when calling mkinstalldirs
|
||||
# from a parallel make. We use --version in the probe to restrict
|
||||
# ourselves to GNU mkdir, which is thread-safe.
|
||||
case $dirmode in
|
||||
'')
|
||||
if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
|
||||
echo "mkdir -p -- $*"
|
||||
exec mkdir -p -- "$@"
|
||||
else
|
||||
# On NextStep and OpenStep, the `mkdir' command does not
|
||||
# recognize any option. It will interpret all options as
|
||||
# directories to create, and then abort because `.' already
|
||||
# exists.
|
||||
test -d ./-p && rmdir ./-p
|
||||
test -d ./--version && rmdir ./--version
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
|
||||
test ! -d ./--version; then
|
||||
echo "mkdir -m $dirmode -p -- $*"
|
||||
exec mkdir -m "$dirmode" -p -- "$@"
|
||||
else
|
||||
# Clean up after NextStep and OpenStep mkdir.
|
||||
for d in ./-m ./-p ./--version "./$dirmode";
|
||||
do
|
||||
test -d $d && rmdir $d
|
||||
done
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
for file
|
||||
do
|
||||
case $file in
|
||||
/*) pathcomp=/ ;;
|
||||
*) pathcomp= ;;
|
||||
esac
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set fnord $file
|
||||
shift
|
||||
IFS=$oIFS
|
||||
|
||||
for d
|
||||
do
|
||||
test "x$d" = x && continue
|
||||
|
||||
pathcomp=$pathcomp$d
|
||||
case $pathcomp in
|
||||
-*) pathcomp=./$pathcomp ;;
|
||||
esac
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
echo "mkdir $pathcomp"
|
||||
|
||||
mkdir "$pathcomp" || lasterr=$?
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
errstatus=$lasterr
|
||||
else
|
||||
if test ! -z "$dirmode"; then
|
||||
echo "chmod $dirmode $pathcomp"
|
||||
lasterr=
|
||||
chmod "$dirmode" "$pathcomp" || lasterr=$?
|
||||
|
||||
if test ! -z "$lasterr"; then
|
||||
errstatus=$lasterr
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
done
|
||||
|
||||
exit $errstatus
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
AM_CFLAGS = -Wall -O2
|
||||
AM_CFLAGS += -g -Wall -Wstrict-prototypes -I .
|
||||
AM_CFLAGS += -DDEBUG_SUPPORT -DLIBIAX
|
||||
AM_CFLAGS += -fsigned-char
|
||||
# -DDEBUG_DEFAULT
|
||||
AM_CFLAGS += $(UCFLAGS)
|
||||
|
||||
|
||||
pkgdir = $(libdir)
|
||||
pkg_LTLIBRARIES=libiax.la
|
||||
libiax_la_SOURCES = iax2-parser.c iax.c md5.c jitterbuf.c
|
||||
EXTRA_DIST = md5.h frame.h iax-client.h iax2.h iax2-parser.h jitterbuf.h
|
||||
|
||||
install-data-local:
|
||||
mkdir -p $(includedir)/iax
|
||||
install -m 644 md5.h $(includedir)/iax
|
||||
install -m 644 frame.h $(includedir)/iax
|
||||
install -m 644 iax.h $(includedir)/iax
|
||||
install -m 644 iax2.h $(includedir)/iax
|
||||
install -m 644 iax2-parser.h $(includedir)/iax
|
||||
install -m 644 iax-client.h $(includedir)/iax
|
||||
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Signed 16-bit audio data
|
||||
*
|
||||
* Source: answer.raw
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer and Linux Support Services
|
||||
*
|
||||
* Distributed under the terms of the GNU General Public License
|
||||
*
|
||||
*/
|
||||
|
||||
static signed short answer[] = {
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 0x19b7, 0x0245, 0xeee5, 0xb875, 0xd9a4, 0x6018, 0x660a, 0xc3c6,
|
||||
0x8741, 0xff55, 0x4c2e, 0x2146, 0xfed2, 0xf079, 0xcbd4, 0xe561, 0x3c41, 0x3166,
|
||||
0xd425, 0xdc59, 0x2748, 0x087d, 0xc72b, 0xfe3a, 0x4681, 0x14c6, 0xcf45, 0xdd38,
|
||||
0xf8dd, 0x0a39, 0x3a5a, 0x32b9, 0xbfec, 0x957f, 0x15a3, 0x70f4, 0x1d95, 0xbfc4,
|
||||
0xd367, 0xfda0, 0x0dc0, 0x29eb, 0x1fc2, 0xd684, 0xcab1, 0x19c7, 0x29ef, 0xe679,
|
||||
0xe9d0, 0x2b82, 0x151a, 0xca9f, 0xdb68, 0x1f4a, 0x271c, 0x0e2a, 0xfb32, 0xd1b2,
|
||||
0xc8ff, 0x2382, 0x6380, 0x0a52, 0xa118, 0xccbf, 0x2ddc, 0x33fd, 0x0964, 0xf2a4,
|
||||
0xdd81, 0xe092, 0x1a00, 0x325c, 0xf5e3, 0xd6a1, 0x0b6c, 0x1c75, 0xe4f8, 0xe07c,
|
||||
0x2082, 0x2b3e, 0xf445, 0xdaa9, 0xea13, 0xff3c, 0x245c, 0x35c1, 0xf308, 0xab53,
|
||||
0xdf59, 0x4698, 0x3f3b, 0xe7f7, 0xca84, 0xed4d, 0x0c3f, 0x1e94, 0x1c2d, 0xf06f,
|
||||
0xd4df, 0xff34, 0x23d8, 0x001e, 0xe3f1, 0x0b15, 0x2113, 0xf3fd, 0xd768, 0xf9a0,
|
||||
0x1d31, 0x1c6e, 0x0797, 0xe3a0, 0xce6c, 0xfd7b, 0x422a, 0x2c4c, 0xd364, 0xbf42,
|
||||
0x0278, 0x303e, 0x1c51, 0xf737, 0xe25a, 0xe75f, 0x0a8f, 0x22ab, 0x05f4, 0xe3f9,
|
||||
0xf8c4, 0x1705, 0x0162, 0xe49f, 0xfb8b, 0x1e2b, 0x13ac, 0xf044, 0xe07b, 0xf01a,
|
||||
0x1567, 0x2cbf, 0x0b75, 0xd01b, 0xd206, 0x1563, 0x38d7, 0x0f2e, 0xdb32, 0xdc30,
|
||||
0x023b, 0x1e44, 0x16eb, 0xf5f7, 0xe425, 0xfa33, 0x14d5, 0x0968, 0xeff2, 0xf762,
|
||||
0x1137, 0x0e59, 0xf13a, 0xe651, 0xff41, 0x1d60, 0x18fd, 0xf1e6, 0xd75f, 0xf097,
|
||||
0x20ec, 0x27fa, 0xfba4, 0xd5b8, 0xe68e, 0x1657, 0x2518, 0x04f6, 0xe5a3, 0xe976,
|
||||
0x0578, 0x18fa, 0x0a92, 0xec0a, 0xef2a, 0x111f, 0x12f4, 0xeec3, 0xe95e, 0x0d3a,
|
||||
0x18fd, 0xff72, 0xeefc, 0xf114, 0xfaaa, 0x14ee, 0x21db, 0xf56e, 0xcb49, 0xf621,
|
||||
0x3323, 0x1947, 0xe017, 0xe7e9, 0x0819, 0x0707, 0x084c, 0x0f57, 0xf152, 0xdf92,
|
||||
0x104a, 0x28eb, 0xedcc, 0xd4ad, 0x1415, 0x296d, 0xed9a, 0xdf57, 0x0cc2, 0x0d95,
|
||||
0xf7b5, 0x0deb, 0x0b34, 0xd713, 0xea08, 0x38d6, 0x216d, 0xc727, 0xdc32, 0x2cd2,
|
||||
0x1822, 0xe2d5, 0xfeb3, 0x106c, 0xe6e5, 0xf81e, 0x2fe8, 0x01af, 0xc180, 0x037a,
|
||||
0x42d8, 0xf88d, 0xc344, 0x0a4f, 0x2c4e, 0xf19d, 0xebeb, 0x162c, 0xf9e9, 0xde93,
|
||||
0x1b56, 0x2c60, 0xd8aa, 0xce3e, 0x2a41, 0x2eeb, 0xdab1, 0xde32, 0x1c32, 0x0aba,
|
||||
0xeabe, 0x1008, 0x136d, 0xda2f, 0xec3b, 0x31dd, 0x1130, 0xca79, 0xf5b8, 0x3423,
|
||||
0x0274, 0xd27d, 0x035e, 0x1e68, 0xf641, 0xf904, 0x1691, 0xef7d, 0xd57a, 0x1c3b,
|
||||
0x3c23, 0xe881, 0xc274, 0x0af5, 0x2962, 0xfa34, 0xf676, 0x0f71, 0xefcc, 0xe01f,
|
||||
0x19e7, 0x276f, 0xe694, 0xe134, 0x1c3a, 0x0e8b, 0xd8e7, 0xfa81, 0x2f8b, 0x07c5,
|
||||
0xd904, 0xf6fa, 0x0ca5, 0xf9a2, 0x0dc7, 0x2623, 0xec54, 0xbe23, 0x02b6, 0x4296,
|
||||
0x10cd, 0xda61, 0xf11c, 0x0103, 0xf41c, 0x10b4, 0x2a03, 0xf63c, 0xce1a, 0xfdbd,
|
||||
0x1fb4, 0xfc51, 0xf727, 0x1c8a, 0x04ff, 0xcf41, 0xec05, 0x2913, 0x1ce8, 0xf70c,
|
||||
0xf744, 0xede8, 0xdd77, 0x0d99, 0x43f1, 0x119c, 0xc14f, 0xd60e, 0x17cb, 0x1e19,
|
||||
0x0d4e, 0x0c95, 0xeed1, 0xcdf4, 0xf7a5, 0x331f, 0x1cd0, 0xeb17, 0xf082, 0xfb19,
|
||||
0xe899, 0xfdeb, 0x323c, 0x2036, 0xdad3, 0xd134, 0xfd03, 0x1345, 0x1c10, 0x2239,
|
||||
0xf656, 0xbc22, 0xdc3f, 0x3392, 0x3d59, 0xfd77, 0xdb4d, 0xe23f, 0xedbe, 0x0f7e,
|
||||
0x35cc, 0x1947, 0xd5dc, 0xd1bf, 0x035d, 0x16fc, 0x1174, 0x1675, 0x0249, 0xd2d4,
|
||||
0xd851, 0x184d, 0x32fe, 0x0f91, 0xee14, 0xe1e6, 0xdf9b, 0x016b, 0x3668, 0x2b2b,
|
||||
0xe20c, 0xc554, 0xf257, 0x1c05, 0x1fc5, 0x14f0, 0xf891, 0xd41c, 0xdf83, 0x1865,
|
||||
0x2de1, 0x0b16, 0xed58, 0xea0c, 0xea79, 0xfbd9, 0x22af, 0x2732, 0xf62f, 0xd389,
|
||||
0xe7d9, 0x0b39, 0x1cdc, 0x1de3, 0x038a, 0xd809, 0xd5f7, 0x0b55, 0x305e, 0x1910,
|
||||
0xf02e, 0xe089, 0xe7c7, 0x0195, 0x2265, 0x21da, 0xf743, 0xd8f2, 0xe978, 0x09a1,
|
||||
0x190a, 0x17c5, 0x045a, 0xe46d, 0xdd06, 0xffb2, 0x2293, 0x1cfe, 0xfd4d, 0xe4f9,
|
||||
0xe310, 0xfaf1, 0x1d22, 0x2376, 0x0113, 0xde3a, 0xe21b, 0x0204, 0x1ba1, 0x1bd6,
|
||||
0x0333, 0xe563, 0xe104, 0xfd51, 0x1bc1, 0x1ccf, 0x0285, 0xe757, 0xe35e, 0xfaf2,
|
||||
0x185d, 0x1d46, 0x06b7, 0xec13, 0xe108, 0xef6e, 0x121d, 0x2a17, 0x16a6, 0xe32c,
|
||||
0xc9a9, 0xf070, 0x2f48, 0x3788, 0xfa4e, 0xc32a, 0xd9c2, 0x1fa1, 0x36fe, 0x07fa,
|
||||
0xd9e4, 0xe577, 0x0e5e, 0x1755, 0xfb53, 0xed71, 0x0540, 0x19e0, 0x0301, 0xdc97,
|
||||
0xe391, 0x1937, 0x367c, 0x0bc9, 0xca4c, 0xc96b, 0x105d, 0x461f, 0x2416, 0xd481,
|
||||
0xbc97, 0xf8b7, 0x39af, 0x2ec9, 0xecc6, 0xcb50, 0xeee3, 0x1ffe, 0x1e8e, 0xf700,
|
||||
0xe66a, 0xff58, 0x149f, 0x02e5, 0xe792, 0xf2d8, 0x1a4d, 0x225a, 0xf642, 0xce7f,
|
||||
0xe6a6, 0x25e2, 0x38f5, 0x01d0, 0xc50f, 0xd243, 0x19bd, 0x3fc6, 0x14f0, 0xd2d7,
|
||||
0xcdb6, 0x069a, 0x2ffe, 0x1847, 0xe6f8, 0xdf0a, 0x0337, 0x1a90, 0x067a, 0xeb5b,
|
||||
0xf541, 0x143b, 0x14f2, 0xf092, 0xdc02, 0xfb91, 0x28a3, 0x2274, 0xeaa8, 0xc9e7,
|
||||
0xef48, 0x2d01, 0x322e, 0xf6d2, 0xc7cb, 0xe13b, 0x1fda, 0x3217, 0x0458, 0xd690,
|
||||
0xe2bf, 0x11c4, 0x21d5, 0x0291, 0xe5c8, 0xf3a9, 0x12ba, 0x11aa, 0xf22b, 0xe627,
|
||||
0x03ec, 0x219a, 0x1036, 0xe2f2, 0xd93f, 0x059c, 0x2ed6, 0x1b75, 0xe227, 0xce55,
|
||||
0xfb19, 0x2de0, 0x2477, 0xed08, 0xd148, 0xf307, 0x21d4, 0x2002, 0xf543, 0xdeac,
|
||||
0xf7f9, 0x18a9, 0x11d6, 0xf0ef, 0xe8e4, 0x05ea, 0x1ba5, 0x0727, 0xe448, 0xe748,
|
||||
0x100e, 0x265e, 0x07fc, 0xdbae, 0xde78, 0x0efa, 0x2ce0, 0x0f94, 0xddf1, 0xd9ea,
|
||||
0x0797, 0x28f6, 0x12eb, 0xe60c, 0xdf46, 0x0469, 0x1fbb, 0x0ced, 0xe9f6, 0xe95f,
|
||||
0x09fe, 0x1ab9, 0x02cb, 0xe5a4, 0xef2a, 0x1327, 0x1d7b, 0xfd07, 0xde3d, 0xed9c,
|
||||
0x17e5, 0x22e7, 0xfe3a, 0xdb38, 0xe9b9, 0x161a, 0x2416, 0x0175, 0xde3d, 0xe9de,
|
||||
0x1294, 0x1fc9, 0x00ea, 0xe2a7, 0xeee2, 0x1298, 0x1a7d, 0xfc1d, 0xe3bb, 0xf47a,
|
||||
0x1642, 0x185e, 0xf727, 0xe1af, 0xf709, 0x19c3, 0x18e7, 0xf50d, 0xe010, 0xf75b,
|
||||
0x1a9c, 0x18d8, 0xf4c5, 0xe0c9, 0xf865, 0x1a1c, 0x16d5, 0xf3a6, 0xe257, 0xfaf2,
|
||||
0x1a44, 0x14d5, 0xf34f, 0xe4b6, 0xfc77, 0x17d5, 0x0ff8, 0xf133, 0xe8b7, 0x0344,
|
||||
0x1a37, 0x0ad5, 0xe95e, 0xe61a, 0x08a5, 0x227e, 0x0e33, 0xe4a7, 0xdd70, 0x03b0,
|
||||
0x25f4, 0x17b2, 0xec0a, 0xdb4e, 0xf898, 0x1ba3, 0x18f6, 0xf973, 0xe87f, 0xf77a,
|
||||
0x0b93, 0x096c, 0xfb0e, 0xfb03, 0x0896, 0x0940, 0xf51d, 0xe904, 0xfdc7, 0x1dda,
|
||||
0x1bf9, 0xf29b, 0xd37f, 0xea1b, 0x1f37, 0x3175, 0x07eb, 0xd3f7, 0xd46b, 0x077d,
|
||||
0x2eeb, 0x1e67, 0xeeae, 0xd8c7, 0xef85, 0x1119, 0x18d3, 0x088e, 0xf953, 0xf5ad,
|
||||
0xf556, 0xf63d, 0x0234, 0x167a, 0x19a1, 0xfbf9, 0xd873, 0xdd4b, 0x0f06, 0x3748,
|
||||
0x21e6, 0xe181, 0xc032, 0xe79a, 0x2bec, 0x3e76, 0x0b1b, 0xce41, 0xcb23, 0xff96,
|
||||
0x2d79, 0x26d1, 0xfcc7, 0xdf8a, 0xe525, 0xfd83, 0x10f1, 0x16d7, 0x0f50, 0xfaea,
|
||||
0xe3f1, 0xe20f, 0x0158, 0x27d9, 0x2866, 0xf96f, 0xcb34, 0xd563, 0x11d6, 0x3d25,
|
||||
0x2424, 0xe254, 0xc2c9, 0xe7cd, 0x248d, 0x34f5, 0x0c42, 0xdcd0, 0xd827, 0xfa65,
|
||||
0x19eb, 0x1b50, 0x0721, 0xf396, 0xeb9c, 0xefde, 0x0016, 0x1594, 0x1cc1, 0x0658,
|
||||
0xe22b, 0xd852, 0xfb3e, 0x2923, 0x2c78, 0xfc87, 0xcdb5, 0xd69c, 0x0e3c, 0x3527,
|
||||
0x201f, 0xe993, 0xcf9e, 0xeb21, 0x183f, 0x25ea, 0x0c93, 0xed4d, 0xe5f9, 0xf548,
|
||||
0x07fb, 0x117c, 0x0ff2, 0x0398, 0xf08c, 0xe628, 0xf489, 0x143b, 0x2419, 0x0ccf,
|
||||
0xe2cc, 0xd5a6, 0xf861, 0x2615, 0x2a1b, 0xfeb4, 0xd543, 0xdc53, 0x09b4, 0x2901,
|
||||
0x19ff, 0xf24a, 0xde86, 0xeec4, 0x0b7b, 0x1733, 0x0d0a, 0xfc24, 0xf1bb, 0xf110,
|
||||
0xfa03, 0x0a0f, 0x15d4, 0x0e21, 0xf435, 0xe17e, 0xee90, 0x1225, 0x2527, 0x0efa,
|
||||
0xe61f, 0xd916, 0xf7b8, 0x1f50, 0x2326, 0x0099, 0xe01e, 0xe473, 0x0491, 0x1b37,
|
||||
0x1360, 0xfb17, 0xecd9, 0xf20d, 0x0051, 0x0aec, 0x0d4a, 0x073d, 0xfa5a, 0xeeb8,
|
||||
0xf165, 0x0516, 0x17dc, 0x12da, 0xf71b, 0xe213, 0xed85, 0x0eef, 0x20c8, 0x0e09,
|
||||
0xebcc, 0xe0d4, 0xf848, 0x1637, 0x19d6, 0x026b, 0xec09, 0xed00, 0xff9b, 0x0e5a,
|
||||
0x0d6b, 0x026c, 0xf865, 0xf4da, 0xf888, 0x025a, 0x0cbb, 0x0d53, 0xff96, 0xeefa,
|
||||
0xee80, 0x021c, 0x15d6, 0x126a, 0xf9c1, 0xe724, 0xf017, 0x0aa1, 0x18b6, 0x0b4e,
|
||||
0xf2d7, 0xea91, 0xf957, 0x0cac, 0x1061, 0x03f4, 0xf6ad, 0xf476, 0xfbdf, 0x0489,
|
||||
0x08b1, 0x06df, 0xffcf, 0xf766, 0xf537, 0xfddf, 0x0ad4, 0x0e15, 0x01da, 0xf205,
|
||||
0xf0a0, 0x0082, 0x1066, 0x0e41, 0xfc71, 0xef1b, 0xf4ad, 0x05cd, 0x0f32, 0x07ed,
|
||||
0xf9c8, 0xf401, 0xfa93, 0x04af, 0x088c, 0x04a7, 0xfe15, 0xf9f1, 0xfa64, 0xff1e,
|
||||
0x0539, 0x078c, 0x02af, 0xfa1a, 0xf69d, 0xfd09, 0x075b, 0x0a3d, 0x01f2, 0xf761,
|
||||
0xf642, 0xffa7, 0x08f3, 0x0830, 0xff05, 0xf7db, 0xf9bc, 0x0174, 0x068b, 0x04b2,
|
||||
0xfeff, 0xfb39, 0xfc1a, 000000, 0x0371, 0x03d7, 0x00fe, 0xfd37, 0xfbe0, 0xfe78,
|
||||
0x02af, 0x044a, 0x0180, 0xfd43, 0xfc00, 0xfed1, 0x02aa, 0x0346, 0x00dd, 0xfde0,
|
||||
0xfbfe, 0x0114, 0x0987, 0x04bc, 0xf49d, 0xf23a, 0x06ab, 0x162e, 0x0544, 0xe76b,
|
||||
0xea25, 0x1015, 0x2474, 0x0431, 0xd7d3, 0xe1ec, 0x1923, 0x2df5, 0x01cd, 0xd386,
|
||||
0xe3d9, 0x1b9d, 0x2c62, 0xfeb8, 0xd31a, 0xe6ba, 0x1dbd, 0x2abb, 0xfbab, 0xd2ed,
|
||||
0xe9ab, 0x1fa7, 0x28ef, 0xf8b3, 0xd2f5, 0xeca5, 0x2160, 0x26fd, 0xf5d7, 0xd334,
|
||||
0xefa1, 0x22e5, 0x24ea, 0xf31b, 0xd3a9, 0xf29f, 0x2435, 0x22b6, 0xf07e, 0xd44e,
|
||||
0xf59b, 0x2551, 0x2067, 0xee08, 0xd527, 0xf88e, 0x2639, 0x1e00, 0xebb6, 0xd62d,
|
||||
0xfb77, 0x26eb, 0x1b85, 0xe98b, 0xd75f, 0xfe51, 0x276b, 0x18f9, 0xe78e, 0xd8b9,
|
||||
0x011a, 0x27b6, 0x1660, 0xe5bb, 0xda3a, 0x03cc, 0x27cf, 0x13bd, 0xe415, 0xdbdf,
|
||||
0x066a, 0x27b7, 0x1117, 0xe29e, 0xdda5, 0x08ec, 0x276e, 0x0e6d, 0xe154, 0xdf89,
|
||||
0x0b52, 0x26f6, 0x0bc7, 0xe039, 0xe185, 0x0d96, 0x2653, 0x0924, 0xdf4e, 0xe399,
|
||||
0x0fb9, 0x2584, 0x068b, 0xde93, 0xe5c0, 0x11b8, 0x248e, 0x03fd, 0xde08, 0xe7f8,
|
||||
0x1390, 0x2372, 0x0180, 0xddaa, 0xea3c, 0x1544, 0x2231, 0xff12, 0xdd7a, 0xec89,
|
||||
0x16cf, 0x20d0, 0xfcb9, 0xdd77, 0xeedb, 0x1831, 0x1f52, 0xfa77, 0xdd9f, 0xf132,
|
||||
0x1969, 0x1db7, 0xf850, 0xddf1, 0xf385, 0x1a75, 0x1c06, 0xf645, 0xde6b, 0xf5d7,
|
||||
0x1b5b, 0x1a3f, 0xf457, 0xdf0d, 0xf820, 0x1c13, 0x1867, 0xf288, 0xdfd2, 0xfa5f,
|
||||
0x1ca1, 0x167f, 0xf0db, 0xe0ba, 0xfc92, 0x1d06, 0x148b, 0xef50, 0xe1c1, 0xfeb5,
|
||||
0x1d43, 0x1290, 0xede9, 0xe2e6, 0x00c6, 0x1d58, 0x108e, 0xeca7, 0xe426, 0x02c4,
|
||||
0x1d45, 0x0e8a, 0xeb8a, 0xe57f, 0x04a9, 0x1d0e, 0x0c87, 0xea92, 0xe6ec, 0x0677,
|
||||
0x1cb2, 0x0a87, 0xe9be, 0xe86e, 0x082a, 0x1c34, 0x088b, 0xe912, 0xe9fe, 0x09c1,
|
||||
0x1b95, 0x069c, 0xe88c, 0xeb9c, 0x0b3a, 0x1ad9, 0x04b6, 0xe82a, 0xed43, 0x0c96,
|
||||
0x1a00, 0x02df, 0xe7eb, 0xeef3, 0x0dd0, 0x190d, 0x0116, 0xe7d0, 0xf0a8, 0x0eec,
|
||||
0x1804, 0xff61, 0xe7d8, 0xf25d, 0x0fe6, 0x16e3, 0xfdc0, 0xe800, 0xf412, 0x10bf,
|
||||
0x15b1, 0xfc36, 0xe848, 0xf5c5, 0x1176, 0x146e, 0xfac2, 0xe8ad, 0xf771, 0x120d,
|
||||
0x1320, 0xf969, 0xe92e, 0xf913, 0x1282, 0x11c4, 0xf828, 0xe9cb, 0xfaac, 0x12d8,
|
||||
0x1062, 0xf703, 0xea7e, 0xfc38, 0x130e, 0x0efa, 0xf5fb, 0xeb49, 0xfdb5, 0x1325,
|
||||
0x0d8e, 0xf50e, 0xec26, 0xff20, 0x131e, 0x0c21, 0xf43f, 0xed15, 0x007a, 0x12fa,
|
||||
0x0ab6, 0xf38d, 0xee15, 0x01be, 0x12bd, 0x094f, 0xf2f9, 0xef22, 0x02ef, 0x1265,
|
||||
0x07f0, 0xf283, 0xf037, 0x0408, 0x11f6, 0x0699, 0xf226, 0xf156, 0x050a, 0x1170,
|
||||
0x054b, 0xf1e8, 0xf27a, 0x05f4, 0x10d8, 0x040c, 0xf1c5, 0xf3a3, 0x06c2, 0x102c,
|
||||
0x02da, 0xf1bc, 0xf4cc, 0x0779, 0x0f71, 0x01b7, 0xf1cc, 0xf5f5, 0x0815, 0x0ea7,
|
||||
0x00a8, 0xf1f4, 0xf719, 0x0899, 0x0dd2, 0xffab, 0xf233, 0xf839, 0x0902, 0x0cf4,
|
||||
0xfec0, 0xf288, 0xf950, 0x0952, 0x0c0e, 0xfdec, 0xf2ee, 0xfa5d, 0x0989, 0x0b23,
|
||||
0xfd2d, 0xf368, 0xfb62, 0x09a7, 0x0a35, 0xfc85, 0xf3f1, 0xfc58, 0x09af, 0x0946,
|
||||
0xfbf2, 0xf488, 0xfd3f, 0x09a1, 0x0859, 0xfb77, 0xf52c, 0xfe17, 0x097d, 0x076f,
|
||||
0xfb14, 0xf5d8, 0xfede, 0x0945, 0x068a, 0xfac6, 0xf68d, 0xff93, 0x08fb, 0x05ad,
|
||||
0xfa8e, 0xf747, 0x0034, 0x08a1, 0x04da, 0xfa6f, 0xf805, 0x00c2, 0x0836, 0x0410,
|
||||
0xfa63, 0xf8c6, 0x013c, 0x07bf, 0x0354, 0xfa6c, 0xf985, 0x01a1, 0x073b, 0x02a4,
|
||||
0xfa8a, 0xfa43, 0x01f1, 0x06af, 0x0204, 0xfab9, 0xfafc, 0x022c, 0x0619, 0x0175,
|
||||
0xfafa, 0xfbae, 0x0252, 0x057f, 0x00f6, 0xfb4b, 0xfc5a, 0x0263, 0x04e0, 0x008b,
|
||||
0xfbaa, 0xfcfa, 0x0262, 0x0440, 0x0032, 0xfc16, 0xfd90, 0x024b, 0x03a0, 0xffec,
|
||||
0xfc8c, 0xfe19, 0x0225, 0x0301, 0xffb9, 0xfd0c, 0xfe93, 0x01ea, 0x0267, 0xff9c,
|
||||
0xfd95, 0xfefe, 0x01a0, 0x01d3, 0xff90, 0xfe22, 0xff5a, 0x0147, 0x0145, 0xff99,
|
||||
0xfeb3, 0xffa1, 0x00e0, 0x00c3, 0xffb6, 0xff46, 0xffd9, 0x006d, 0x004b, 0xffe5,
|
||||
0xffda, 0xfffc, 000000, 0xfffe, 000000, 0xffff, 000000, 0xffff, 0xffff, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
|
||||
000000 };
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/* busy.h: Generated from frequencies 480 and 620
|
||||
by gensound. 400 samples */
|
||||
static short busy[400] = {
|
||||
0, 13697, 24766, 31109, 31585, 26222, 16198, 3569,
|
||||
-9162, -19575, -25812, -26935, -23069, -15322, -5493, 4339,
|
||||
12277, 16985, 17934, 15440, 10519, 4585, -908, -4827,
|
||||
-6592, -6269, -4489, -2220, -467, 30, -983, -3203,
|
||||
-5839, -7844, -8215, -6301, -2035, 3975, 10543, 16141,
|
||||
19260, 18787, 14322, 6338, -3845, -14296, -22858, -27611,
|
||||
-27309, -21691, -11585, 1213, 14285, 25068, 31388, 31915,
|
||||
26457, 16010, 2568, -11282, -22885, -30054, -31509, -27120,
|
||||
-17908, -5805, 6760, 17379, 24147, 26028, 23020, 16094,
|
||||
6931, -2478, -10279, -15136, -16474, -14538, -10253, -4949,
|
||||
0, 3515, 5052, 4688, 3045, 1069, -268, -272,
|
||||
1269, 3996, 7067, 9381, 9889, 7910, 3365, -3123,
|
||||
-10320, -16622, -20424, -20510, -16384, -8448, 2006, 13026,
|
||||
22383, 28040, 28613, 23696, 13996, 1232, -12193, -23670,
|
||||
-30918, -32459, -27935, -18190, -5103, 8795, 20838, 28764,
|
||||
31164, 27753, 19395, 7893, -4412, -15136, -22342, -24909,
|
||||
-22717, -16609, -8143, 780, 8361, 13272, 14909, 13455,
|
||||
9758, 5067, 678, -2387, -3624, -3133, -1538, 224,
|
||||
1209, 751, -1315, -4580, -8145, -10848, -11585, -9628,
|
||||
-4878, 2038, 9844, 16867, 21403, 22124, 18429, 10638,
|
||||
0, -11524, -21643, -28211, -29702, -25561, -16364, -3737,
|
||||
9946, 22044, 30180, 32733, 29182, 20210, 7573, -6269,
|
||||
-18655, -27259, -30558, -28117, -20645, -9807, 2148, 12878,
|
||||
20426, 23599, 22173, 16865, 9117, 731, -6552, -11426,
|
||||
-13269, -12216, -9050, -4941, -1118, 1460, 2335, 1635,
|
||||
0, -1635, -2335, -1460, 1118, 4941, 9050, 12216,
|
||||
13269, 11426, 6552, -731, -9117, -16865, -22173, -23599,
|
||||
-20426, -12878, -2148, 9807, 20645, 28117, 30558, 27259,
|
||||
18655, 6269, -7573, -20210, -29182, -32733, -30180, -22044,
|
||||
-9946, 3737, 16364, 25561, 29702, 28211, 21643, 11524,
|
||||
0, -10638, -18429, -22124, -21403, -16867, -9844, -2038,
|
||||
4878, 9628, 11585, 10848, 8145, 4580, 1315, -751,
|
||||
-1209, -224, 1538, 3133, 3624, 2387, -678, -5067,
|
||||
-9758, -13455, -14909, -13272, -8361, -780, 8143, 16609,
|
||||
22717, 24909, 22342, 15136, 4412, -7893, -19395, -27753,
|
||||
-31164, -28764, -20838, -8795, 5103, 18190, 27935, 32459,
|
||||
30918, 23670, 12193, -1232, -13996, -23696, -28613, -28040,
|
||||
-22383, -13026, -2006, 8448, 16384, 20510, 20424, 16622,
|
||||
10320, 3123, -3365, -7910, -9889, -9381, -7067, -3996,
|
||||
-1269, 272, 268, -1069, -3045, -4688, -5052, -3515,
|
||||
0, 4949, 10253, 14538, 16474, 15136, 10279, 2478,
|
||||
-6931, -16094, -23020, -26028, -24147, -17379, -6760, 5805,
|
||||
17908, 27120, 31509, 30054, 22885, 11282, -2568, -16010,
|
||||
-26457, -31915, -31388, -25068, -14285, -1213, 11585, 21691,
|
||||
27309, 27611, 22858, 14296, 3845, -6338, -14322, -18787,
|
||||
-19260, -16141, -10543, -3975, 2035, 6301, 8215, 7844,
|
||||
5839, 3203, 983, -30, 467, 2220, 4489, 6269,
|
||||
6592, 4827, 908, -4585, -10519, -15440, -17934, -16985,
|
||||
-12277, -4339, 5493, 15322, 23069, 26935, 25812, 19575,
|
||||
9162, -3569, -16198, -26222, -31585, -31109, -24766, -13697,
|
||||
|
||||
};
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/* dialtone.h: Generated from frequencies 350 and 440
|
||||
by gensound. 800 samples */
|
||||
static short dialtone[800] = {
|
||||
0, 9997, 19004, 26133, 30692, 32251, 30690, 26206,
|
||||
19286, 10657, 1206, -8116, -16396, -22848, -26895, -28221,
|
||||
-26797, -22878, -16960, -9723, -1954, 5545, 12044, 16954,
|
||||
19887, 20687, 19434, 16420, 12107, 7061, 1881, -2866,
|
||||
-6721, -9365, -10657, -10634, -9491, -7547, -5190, -2822,
|
||||
-801, 607, 1263, 1168, 454, -633, -1784, -2669,
|
||||
-2993, -2548, -1247, 855, 3558, 6538, 9388, 11665,
|
||||
12955, 12933, 11408, 8370, 3996, -1349, -7152, -12797,
|
||||
-17635, -21060, -22583, -21895, -18914, -13807, -6985, 934,
|
||||
9180, 16913, 23309, 27654, 29422, 28342, 24429, 17998,
|
||||
9630, 123, -9589, -18538, -25813, -30667, -32588, -31360,
|
||||
-27088, -20185, -11332, -1411, 8594, 17694, 24997, 29805,
|
||||
31675, 30473, 26374, 19844, 11585, 2455, -6618, -14745,
|
||||
-21156, -25284, -26815, -25713, -22213, -16785, -10073, -2824,
|
||||
4203, 10318, 14969, 17794, 18653, 17628, 14998, 11197,
|
||||
6753, 2217, -1899, -5189, -7386, -8388, -8261, -7212,
|
||||
-5555, -3657, -1881, -536, 169, 157, -515, -1664,
|
||||
-3009, -4217, -4954, -4940, -3996, -2080, 697, 4081,
|
||||
7689, 11059, 13710, 15199, 15187, 13489, 10114, 5272,
|
||||
-630, -7031, -13263, -18632, -22491, -24320, -23794, -20823,
|
||||
-15582, -8498, -218, 8457, 16651, 23507, 28276, 30407,
|
||||
29606, 25876, 19524, 11134, 1511, -8401, -17616, -25208,
|
||||
-30406, -32682, -31800, -27845, -21215, -12576, -2796, 7150,
|
||||
16278, 23700, 28713, 30868, 30015, 26312, 20199, 12351,
|
||||
3598, -5164, -13071, -19378, -23531, -25223, -24413, -21318,
|
||||
-16384, -10218, -3526, 2980, 8655, 12985, 15642, 16505,
|
||||
15661, 13381, 10073, 6228, 2348, -1110, -3796, -5495,
|
||||
-6152, -5863, -4853, -3434, -1954, -744, -62, -60,
|
||||
-757, -2037, -3664, -5317, -6637, -7283, -6985, -5590,
|
||||
-3096, 334, 4390, 8631, 12544, 15605, 17339, 17393,
|
||||
15582, 11928, 6672, 258, -6705, -13506, -19403, -23711,
|
||||
-25879, -25558, -22653, -17341, -10061, -1480, 7570, 16185,
|
||||
23475, 28661, 31164, 30670, 27167, 20951, 12603, 2930,
|
||||
-7116, -16540, -24401, -29915, -32533, -32003, -28391, -22075,
|
||||
-13704, -4128, 5690, 14781, 22262, 27432, 29838, 29319,
|
||||
26014, 20339, 12940, 4614, -3777, -11401, -17540, -21660,
|
||||
-23463, -22908, -20199, -15755, -10150, -4044, 1898, 7079,
|
||||
11030, 13459, 14268, 13555, 11585, 8745, 5487, 2268,
|
||||
-511, -2559, -3716, -3975, -3468, -2440, -1206, -101,
|
||||
578, 618, -78, -1470, -3382, -5524, -7531, -9018,
|
||||
-9630, -9103, -7308, -4280, -226, 4483, 9357, 13829,
|
||||
17329, 19352, 19524, 17659, 13788, 8177, 1302, -6184,
|
||||
-13528, -19945, -24710, -27240, -27167, -24381, -19058, -11646,
|
||||
-2830, 6539, 15528, 23219, 28806, 31685, 31520, 28282,
|
||||
22254, 14010, 4355, -5759, -15331, -23411, -29203, -32144,
|
||||
-31966, -28714, -22748, -14695, -5384, 4241, 13228, 20707,
|
||||
25981, 28600, 28391, 25479, 20256, 13337, 5482, -2482,
|
||||
-9761, -15668, -19694, -21556, -21215, -18865, -14902, -9864,
|
||||
-4366, 975, 5614, 9130, 11270, 11967, 11332, 9628,
|
||||
7223, 4536, 1976, -113, -1495, -2071, -1882, -1102,
|
||||
0, 1102, 1882, 2071, 1495, 113, -1976, -4536,
|
||||
-7223, -9628, -11332, -11967, -11270, -9130, -5614, -975,
|
||||
4366, 9864, 14902, 18865, 21215, 21556, 19694, 15668,
|
||||
9761, 2482, -5482, -13337, -20256, -25479, -28391, -28600,
|
||||
-25981, -20707, -13228, -4241, 5384, 14695, 22748, 28714,
|
||||
31966, 32144, 29203, 23411, 15331, 5759, -4355, -14010,
|
||||
-22254, -28282, -31520, -31685, -28806, -23219, -15528, -6539,
|
||||
2830, 11646, 19058, 24381, 27167, 27240, 24710, 19945,
|
||||
13528, 6184, -1302, -8177, -13788, -17659, -19524, -19352,
|
||||
-17329, -13829, -9357, -4483, 226, 4280, 7308, 9103,
|
||||
9630, 9018, 7531, 5524, 3382, 1470, 78, -618,
|
||||
-578, 101, 1206, 2440, 3468, 3975, 3716, 2559,
|
||||
511, -2268, -5487, -8745, -11585, -13555, -14268, -13459,
|
||||
-11030, -7079, -1898, 4044, 10150, 15755, 20199, 22908,
|
||||
23463, 21660, 17540, 11401, 3777, -4614, -12940, -20339,
|
||||
-26014, -29319, -29838, -27432, -22262, -14781, -5690, 4128,
|
||||
13704, 22075, 28391, 32003, 32533, 29915, 24401, 16540,
|
||||
7116, -2930, -12603, -20951, -27167, -30670, -31164, -28661,
|
||||
-23475, -16185, -7570, 1480, 10061, 17341, 22653, 25558,
|
||||
25879, 23711, 19403, 13506, 6705, -258, -6672, -11928,
|
||||
-15582, -17393, -17339, -15605, -12544, -8631, -4390, -334,
|
||||
3096, 5590, 6985, 7283, 6637, 5317, 3664, 2037,
|
||||
757, 60, 62, 744, 1954, 3434, 4853, 5863,
|
||||
6152, 5495, 3796, 1110, -2348, -6228, -10073, -13381,
|
||||
-15661, -16505, -15642, -12985, -8655, -2980, 3526, 10218,
|
||||
16384, 21318, 24413, 25223, 23531, 19378, 13071, 5164,
|
||||
-3598, -12351, -20199, -26312, -30015, -30868, -28713, -23700,
|
||||
-16278, -7150, 2796, 12576, 21215, 27845, 31800, 32682,
|
||||
30406, 25208, 17616, 8401, -1511, -11134, -19524, -25876,
|
||||
-29606, -30407, -28276, -23507, -16651, -8457, 218, 8498,
|
||||
15582, 20823, 23794, 24320, 22491, 18632, 13263, 7031,
|
||||
630, -5272, -10114, -13489, -15187, -15199, -13710, -11059,
|
||||
-7689, -4081, -697, 2080, 3996, 4940, 4954, 4217,
|
||||
3009, 1664, 515, -157, -169, 536, 1881, 3657,
|
||||
5555, 7212, 8261, 8388, 7386, 5189, 1899, -2217,
|
||||
-6753, -11197, -14998, -17628, -18653, -17794, -14969, -10318,
|
||||
-4203, 2824, 10073, 16785, 22213, 25713, 26815, 25284,
|
||||
21156, 14745, 6618, -2455, -11585, -19844, -26374, -30473,
|
||||
-31675, -29805, -24997, -17694, -8594, 1411, 11332, 20185,
|
||||
27088, 31360, 32588, 30667, 25813, 18538, 9589, -123,
|
||||
-9630, -17998, -24429, -28342, -29422, -27654, -23309, -16913,
|
||||
-9180, -934, 6985, 13807, 18914, 21895, 22583, 21060,
|
||||
17635, 12797, 7152, 1349, -3996, -8370, -11408, -12933,
|
||||
-12955, -11665, -9388, -6538, -3558, -855, 1247, 2548,
|
||||
2993, 2669, 1784, 633, -454, -1168, -1263, -607,
|
||||
801, 2822, 5190, 7547, 9491, 10634, 10657, 9365,
|
||||
6721, 2866, -1881, -7061, -12107, -16420, -19434, -20687,
|
||||
-19887, -16954, -12044, -5545, 1954, 9723, 16960, 22878,
|
||||
26797, 28221, 26895, 22848, 16396, 8116, -1206, -10657,
|
||||
-19286, -26206, -30690, -32251, -30692, -26133, -19004, -9997,
|
||||
|
||||
};
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* libiax: An implementation of the Inter-Asterisk eXchange protocol
|
||||
*
|
||||
* Asterisk internal frame definitions.
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser General Public License. Other components of
|
||||
* Asterisk are distributed under The GNU General Public License
|
||||
* only.
|
||||
*/
|
||||
|
||||
#ifndef _LIBIAX_FRAME_H
|
||||
#define _LIBIAX_FRAME_H
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Frame types */
|
||||
#define AST_FRAME_DTMF 1 /* A DTMF digit, subclass is the digit */
|
||||
#define AST_FRAME_VOICE 2 /* Voice data, subclass is AST_FORMAT_* */
|
||||
#define AST_FRAME_VIDEO 3 /* Video frame, maybe?? :) */
|
||||
#define AST_FRAME_CONTROL 4 /* A control frame, subclass is AST_CONTROL_* */
|
||||
#define AST_FRAME_NULL 5 /* An empty, useless frame */
|
||||
#define AST_FRAME_IAX 6 /* Inter Aterisk Exchange private frame type */
|
||||
#define AST_FRAME_TEXT 7 /* Text messages */
|
||||
#define AST_FRAME_IMAGE 8 /* Image Frames */
|
||||
#define AST_FRAME_HTML 9 /* HTML Frames */
|
||||
#define AST_FRAME_CNG 10 /* Comfort Noise frame (subclass is level of CNG in -dBov) */
|
||||
|
||||
/* HTML subclasses */
|
||||
#define AST_HTML_URL 1 /* Sending a URL */
|
||||
#define AST_HTML_DATA 2 /* Data frame */
|
||||
#define AST_HTML_BEGIN 4 /* Beginning frame */
|
||||
#define AST_HTML_END 8 /* End frame */
|
||||
#define AST_HTML_LDCOMPLETE 16 /* Load is complete */
|
||||
#define AST_HTML_NOSUPPORT 17 /* Peer is unable to support HTML */
|
||||
#define AST_HTML_LINKURL 18 /* Send URL and track */
|
||||
#define AST_HTML_UNLINK 19 /* Request no more linkage */
|
||||
#define AST_HTML_LINKREJECT 20 /* Reject LINKURL */
|
||||
|
||||
/* Data formats for capabilities and frames alike */
|
||||
/*! G.723.1 compression */
|
||||
#define AST_FORMAT_G723_1 (1 << 0)
|
||||
/*! GSM compression */
|
||||
#define AST_FORMAT_GSM (1 << 1)
|
||||
/*! Raw mu-law data (G.711) */
|
||||
#define AST_FORMAT_ULAW (1 << 2)
|
||||
/*! Raw A-law data (G.711) */
|
||||
#define AST_FORMAT_ALAW (1 << 3)
|
||||
/*! ADPCM (G.726, 32kbps) */
|
||||
#define AST_FORMAT_G726 (1 << 4)
|
||||
/*! ADPCM (IMA) */
|
||||
#define AST_FORMAT_ADPCM (1 << 5)
|
||||
/*! Raw 16-bit Signed Linear (8000 Hz) PCM */
|
||||
#define AST_FORMAT_SLINEAR (1 << 6)
|
||||
/*! LPC10, 180 samples/frame */
|
||||
#define AST_FORMAT_LPC10 (1 << 7)
|
||||
/*! G.729A audio */
|
||||
#define AST_FORMAT_G729A (1 << 8)
|
||||
/*! SpeeX Free Compression */
|
||||
#define AST_FORMAT_SPEEX (1 << 9)
|
||||
/*! iLBC Free Compression */
|
||||
#define AST_FORMAT_ILBC (1 << 10)
|
||||
/*! Maximum audio format */
|
||||
#define AST_FORMAT_MAX_AUDIO (1 << 15)
|
||||
/*! JPEG Images */
|
||||
#define AST_FORMAT_JPEG (1 << 16)
|
||||
/*! PNG Images */
|
||||
#define AST_FORMAT_PNG (1 << 17)
|
||||
/*! H.261 Video */
|
||||
#define AST_FORMAT_H261 (1 << 18)
|
||||
/*! H.263 Video */
|
||||
#define AST_FORMAT_H263 (1 << 19)
|
||||
/*! H.263+ Video */
|
||||
#define AST_FORMAT_H263p (1 << 20)
|
||||
/*! H.264 Video*/
|
||||
#define AST_FORMAT_H264 (1 << 21)
|
||||
/*! MPEG4 Video*/
|
||||
#define AST_FORMAT_MPEG4 (1 << 22)
|
||||
/*! Theora Video */
|
||||
#define AST_FORMAT_THEORA (1 << 24)
|
||||
/*! Max one */
|
||||
#define AST_FORMAT_MAX_VIDEO (1 << 24)
|
||||
|
||||
/* Control frame types */
|
||||
#define AST_CONTROL_HANGUP 1 /* Other end has hungup */
|
||||
#define AST_CONTROL_RING 2 /* Local ring */
|
||||
#define AST_CONTROL_RINGING 3 /* Remote end is ringing */
|
||||
#define AST_CONTROL_ANSWER 4 /* Remote end has answered */
|
||||
#define AST_CONTROL_BUSY 5 /* Remote end is busy */
|
||||
#define AST_CONTROL_TAKEOFFHOOK 6 /* Make it go off hook */
|
||||
#define AST_CONTROL_OFFHOOK 7 /* Line is off hook */
|
||||
#define AST_CONTROL_CONGESTION 8 /* Congestion (circuits busy) */
|
||||
#define AST_CONTROL_FLASH 9 /* Flash hook */
|
||||
#define AST_CONTROL_WINK 10 /* Wink */
|
||||
#define AST_CONTROL_OPTION 11 /* Set an option */
|
||||
|
||||
#define AST_FRIENDLY_OFFSET 64 /* Reserved header space */
|
||||
|
||||
struct ast_frame {
|
||||
/*! Kind of frame */
|
||||
int frametype;
|
||||
/*! Subclass, frame dependent */
|
||||
int subclass;
|
||||
/*! Length of data */
|
||||
int datalen;
|
||||
/*! Number of 8khz samples in this frame */
|
||||
int samples;
|
||||
/*! Was the data malloc'd? i.e. should we free it when we discard the f
|
||||
rame? */
|
||||
int mallocd;
|
||||
/*! How far into "data" the data really starts */
|
||||
int offset;
|
||||
/*! Optional source of frame for debugging */
|
||||
char *src;
|
||||
/*! Pointer to actual data */
|
||||
void *data;
|
||||
/*! Next/Prev for linking stand alone frames */
|
||||
struct ast_frame *prev;
|
||||
/*! Next/Prev for linking stand alone frames */
|
||||
struct ast_frame *next;
|
||||
/* Unused except
|
||||
if debugging is turned on, but left
|
||||
in the struct
|
||||
so that it can be turned on without
|
||||
requiring a r
|
||||
ecompile of the whole thing */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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 Lesser General Public License (LGPL)
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_IAX_CLIENT_H
|
||||
#define _ASTERISK_IAX_CLIENT_H
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* disable zero-sized array in struct/union warning */
|
||||
#pragma warning(disable:4200)
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define socklen_t int
|
||||
#endif
|
||||
|
||||
#include "frame.h"
|
||||
#include "iax2.h"
|
||||
#include "iax2-parser.h"
|
||||
|
||||
#define MAXSTRLEN 80
|
||||
|
||||
#define IAX_AUTHMETHOD_PLAINTEXT IAX_AUTH_PLAINTEXT
|
||||
#define IAX_AUTHMETHOD_MD5 IAX_AUTH_MD5
|
||||
|
||||
extern char iax_errstr[];
|
||||
|
||||
struct iax_session;
|
||||
|
||||
|
||||
#define IAX_EVENT_CONNECT 0 /* Connect a new call */
|
||||
#define IAX_EVENT_ACCEPT 1 /* Accept a call */
|
||||
#define IAX_EVENT_HANGUP 2 /* Hang up a call */
|
||||
#define IAX_EVENT_REJECT 3 /* Rejected call */
|
||||
#define IAX_EVENT_VOICE 4 /* Voice Data */
|
||||
#define IAX_EVENT_DTMF 5 /* A DTMF Tone */
|
||||
#define IAX_EVENT_TIMEOUT 6 /* Connection timeout... session
|
||||
will be a pointer to free()'d
|
||||
memory! */
|
||||
#define IAX_EVENT_LAGRQ 7 /* Lag request -- Internal use only */
|
||||
#define IAX_EVENT_LAGRP 8 /* Lag Measurement. See event.lag */
|
||||
#define IAX_EVENT_RINGA 9 /* Announce we/they are ringing */
|
||||
#define IAX_EVENT_PING 10 /* Ping -- internal use only */
|
||||
#define IAX_EVENT_PONG 11 /* Pong -- internal use only */
|
||||
#define IAX_EVENT_BUSY 12 /* Report a line busy */
|
||||
#define IAX_EVENT_ANSWER 13 /* Answer the line */
|
||||
|
||||
#define IAX_EVENT_IMAGE 14 /* Send/Receive an image */
|
||||
#define IAX_EVENT_AUTHRQ 15 /* Authentication request */
|
||||
#define IAX_EVENT_AUTHRP 16 /* Authentication reply */
|
||||
|
||||
#define IAX_EVENT_REGREQ 17 /* Registration request */
|
||||
#define IAX_EVENT_REGACK 18 /* Registration reply */
|
||||
#define IAX_EVENT_URL 19 /* URL received */
|
||||
#define IAX_EVENT_LDCOMPLETE 20 /* URL loading complete */
|
||||
|
||||
#define IAX_EVENT_TRANSFER 21 /* Transfer has taken place */
|
||||
|
||||
#define IAX_EVENT_DPREQ 22 /* Dialplan request */
|
||||
#define IAX_EVENT_DPREP 23 /* Dialplan reply */
|
||||
#define IAX_EVENT_DIAL 24 /* Dial on a TBD call */
|
||||
|
||||
#define IAX_EVENT_QUELCH 25 /* Quelch Audio */
|
||||
#define IAX_EVENT_UNQUELCH 26 /* Unquelch Audio */
|
||||
|
||||
#define IAX_EVENT_UNLINK 27 /* Unlink */
|
||||
#define IAX_EVENT_LINKREJECT 28 /* Link Rejection */
|
||||
#define IAX_EVENT_TEXT 29 /* Text Frame :-) */
|
||||
#define IAX_EVENT_REGREJ 30 /* Registration reply */
|
||||
#define IAX_EVENT_LINKURL 31 /* Unlink */
|
||||
#define IAX_EVENT_CNG 32 /* Comfort-noise (almost silence) */
|
||||
#define IAX_EVENT_POKE 33
|
||||
#define IAX_EVENT_VIDEO 34 /* Send/receive video */
|
||||
|
||||
|
||||
/* moved from iax.c to support attended transfer */
|
||||
#define IAX_EVENT_REREQUEST 999
|
||||
#define IAX_EVENT_TXREPLY 1000
|
||||
#define IAX_EVENT_TXREJECT 1001
|
||||
#define IAX_EVENT_TXACCEPT 1002
|
||||
#define IAX_EVENT_TXREADY 1003
|
||||
|
||||
/*
|
||||
* Null event. We use it to notify back the caller that a frame has been
|
||||
* received and is queued for delivery
|
||||
* Applciations should simply ignore it
|
||||
*/
|
||||
#define IAX_EVENT_NULL 65535
|
||||
|
||||
#define IAX_SCHEDULE_FUZZ 0 /* ms of fuzz to drop */
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#if defined(_MSC_VER)
|
||||
typedef int (__stdcall *iax_sendto_t)(SOCKET, const void *, size_t, int,
|
||||
const struct sockaddr *, socklen_t);
|
||||
typedef int (__stdcall *iax_recvfrom_t)(SOCKET, void *, size_t, int,
|
||||
struct sockaddr *, socklen_t *);
|
||||
#else
|
||||
typedef int PASCAL (*iax_sendto_t)(SOCKET, const char *, int, int,
|
||||
const struct sockaddr *, int);
|
||||
typedef int PASCAL (*iax_recvfrom_t)(SOCKET, char *, int, int,
|
||||
struct sockaddr *, int *);
|
||||
#endif
|
||||
#else
|
||||
typedef int (*iax_sendto_t)(int, const void *, size_t, int,
|
||||
const struct sockaddr *, socklen_t);
|
||||
typedef int (*iax_recvfrom_t)(int, void *, size_t, int,
|
||||
struct sockaddr *, socklen_t *);
|
||||
#endif
|
||||
|
||||
struct iax_event {
|
||||
int etype; /* Type of event */
|
||||
int subclass; /* Subclass data (event specific) */
|
||||
unsigned int ts; /* Timestamp */
|
||||
struct iax_session *session; /* Applicable session */
|
||||
int datalen; /* Length of raw data */
|
||||
struct iax_ies ies; /* IE's for IAX2 frames */
|
||||
unsigned char data[0]; /* Raw data if applicable */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* All functions return 0 on success and -1 on failure unless otherwise
|
||||
specified */
|
||||
|
||||
/* Called to initialize IAX structures and sockets. Returns actual
|
||||
portnumber (which it will try preferred portno first, but if not
|
||||
take what it can get */
|
||||
extern int iax_init(int preferredportno);
|
||||
|
||||
/* Get filedescriptor for IAX to use with select or gtk_input_add */
|
||||
extern int iax_get_fd(void);
|
||||
|
||||
/* Find out how many milliseconds until the next scheduled event */
|
||||
extern int iax_time_to_next_event(void);
|
||||
|
||||
/* Generate a new IAX session */
|
||||
extern struct iax_session *iax_session_new(void);
|
||||
|
||||
/* Return exactly one iax event (if there is one pending). If blocking is
|
||||
non-zero, IAX will block until some event is received */
|
||||
extern struct iax_event *iax_get_event(int blocking);
|
||||
|
||||
|
||||
extern int iax_auth_reply(struct iax_session *session, char *password,
|
||||
char *challenge, int methods);
|
||||
|
||||
/* Free an event */
|
||||
extern void iax_event_free(struct iax_event *event);
|
||||
|
||||
struct sockaddr_in;
|
||||
|
||||
/* Front ends for sending events */
|
||||
extern int iax_send_dtmf(struct iax_session *session, char digit);
|
||||
extern int iax_send_voice(struct iax_session *session, int format, unsigned char *data, int datalen, int samples);
|
||||
extern int iax_send_cng(struct iax_session *session, int level, unsigned char *data, int datalen);
|
||||
extern int iax_send_image(struct iax_session *session, int format, unsigned char *data, int datalen);
|
||||
extern int iax_send_url(struct iax_session *session, const char *url, int link);
|
||||
extern int iax_send_text(struct iax_session *session, const char *text);
|
||||
extern int iax_send_ping(struct iax_session *session);
|
||||
extern int iax_load_complete(struct iax_session *session);
|
||||
extern int iax_reject(struct iax_session *session, char *reason);
|
||||
extern int iax_busy(struct iax_session *session);
|
||||
extern int iax_congestion(struct iax_session *session);
|
||||
extern int iax_hangup(struct iax_session *session, char *byemsg);
|
||||
extern int iax_call(struct iax_session *session, const char *cidnum, const char *cidname, const char *ich, const char *lang, int wait, int format, int capability);
|
||||
extern int iax_accept(struct iax_session *session, int format);
|
||||
extern int iax_answer(struct iax_session *session);
|
||||
extern int iax_sendurl(struct iax_session *session, char *url);
|
||||
extern int iax_send_unlink(struct iax_session *session);
|
||||
extern int iax_send_link_reject(struct iax_session *session);
|
||||
extern int iax_ring_announce(struct iax_session *session);
|
||||
extern struct sockaddr_in iax_get_peer_addr(struct iax_session *session);
|
||||
extern int iax_register(struct iax_session *session, const char *hostname, const char *peer, const char *secret, int refresh);
|
||||
extern int iax_unregister(struct iax_session *session, const char *hostname, const char *peer, const char *secret, const char *reason);
|
||||
extern int iax_lag_request(struct iax_session *session);
|
||||
extern int iax_dial(struct iax_session *session, char *number); /* Dial on a TBD call */
|
||||
extern int iax_dialplan_request(struct iax_session *session, char *number); /* Request dialplan status for number */
|
||||
extern int iax_quelch(struct iax_session *session);
|
||||
extern int iax_unquelch(struct iax_session * session);
|
||||
extern int iax_transfer(struct iax_session *session, const char *number);
|
||||
extern int iax_quelch_moh(struct iax_session *session, int MOH);
|
||||
extern int iax_send_video(struct iax_session *session, int format, unsigned char *data, int datalen, int fullframe);
|
||||
extern int iax_send_video_trunk(struct iax_session *session, int format, char *data, int datalen, int fullframe, int ntrunk);
|
||||
|
||||
extern void iax_destroy(struct iax_session * session);
|
||||
|
||||
extern void iax_enable_debug(void);
|
||||
extern void iax_disable_debug(void);
|
||||
|
||||
extern struct timeval iax_tvnow(void);
|
||||
|
||||
/* For attended transfer, application create a new session,
|
||||
* make a call on the new session.
|
||||
* On answer of the new session, call iax_setup_transfer and wait for
|
||||
* IAX_EVENT_TXREADY when both sides are completed succefully or
|
||||
* IAX_EVENT_TXREJECT for either side.
|
||||
* If there are music on hold the it will be stopped by this library.
|
||||
*/
|
||||
extern int iax_setup_transfer(struct iax_session *s0, struct iax_session *s1);
|
||||
|
||||
struct iax_netstat {
|
||||
int jitter;
|
||||
int losspct;
|
||||
int losscnt;
|
||||
int packets;
|
||||
int delay;
|
||||
int dropped;
|
||||
int ooo;
|
||||
};
|
||||
/* fills in rtt, and an iax_netstat structure for each of local/remote directions of call */
|
||||
extern int iax_get_netstats(struct iax_session *s, int *rtt, struct iax_netstat *local, struct iax_netstat *remote);
|
||||
|
||||
|
||||
extern void iax_set_private(struct iax_session *s, void *pvt);
|
||||
extern void *iax_get_private(struct iax_session *s);
|
||||
extern void iax_set_sendto(struct iax_session *s, iax_sendto_t sendto);
|
||||
|
||||
/* to use application networking instead of internal, set call this instead of iax_init,
|
||||
* and pass in sendto and recvfrom replacements. blocking reads may not be implemented */
|
||||
extern void iax_set_networking(iax_sendto_t st, iax_recvfrom_t rf);
|
||||
|
||||
/* destroy an iax session */
|
||||
extern void iax_session_destroy(struct iax_session **session);
|
||||
|
||||
/* To control use of jitter buffer for video event */
|
||||
int iax_video_bypass_jitter(struct iax_session*, int );
|
||||
|
||||
/* Handle externally received frames */
|
||||
struct iax_event *iax_net_process(unsigned char *buf, int len, struct sockaddr_in *sin);
|
||||
extern unsigned int iax_session_get_capability(struct iax_session *s);
|
||||
extern char iax_pref_codec_add(struct iax_session *session, unsigned int format);
|
||||
extern void iax_pref_codec_del(struct iax_session *session, unsigned int format);
|
||||
extern int iax_pref_codec_get(struct iax_session *session, unsigned int *array, int len);
|
||||
|
||||
/* Fine tune jitterbuffer */
|
||||
extern void iax_set_jb_target_extra( long value );
|
||||
|
||||
/* Portable 'decent' random number generation */
|
||||
extern void iax_seed_random(void);
|
||||
extern int iax_random(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASTERISK_IAX_CLIENT_H */
|
||||
+3530
File diff suppressed because it is too large
Load Diff
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* libIAX
|
||||
*
|
||||
* Implementation of Inter-IAXerisk eXchange
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*/
|
||||
|
||||
#ifndef _IAX_H
|
||||
#define _IAX_H
|
||||
|
||||
/* Max version of IAX protocol we support */
|
||||
#define IAX_PROTO_VERSION 1
|
||||
|
||||
#define IAX_MAX_CALLS 32768
|
||||
|
||||
#define IAX_FLAG_FULL 0x8000
|
||||
|
||||
#define IAX_FLAG_SC_LOG 0x80
|
||||
|
||||
#define IAX_MAX_SHIFT 0x1F
|
||||
|
||||
/* Maximum size of an IAX frame (max size of UDP frame) */
|
||||
#define IAX_MAX_BUF_SIZE 65536
|
||||
|
||||
/* Subclass for IAX_FRAME_IAX */
|
||||
#define IAX_COMMAND_NEW 1
|
||||
#define IAX_COMMAND_PING 2
|
||||
#define IAX_COMMAND_PONG 3
|
||||
#define IAX_COMMAND_ACK 4
|
||||
#define IAX_COMMAND_HANGUP 5
|
||||
#define IAX_COMMAND_REJECT 6
|
||||
#define IAX_COMMAND_ACCEPT 7
|
||||
#define IAX_COMMAND_AUTHREQ 8
|
||||
#define IAX_COMMAND_AUTHREP 9
|
||||
#define IAX_COMMAND_INVAL 10
|
||||
#define IAX_COMMAND_LAGRQ 11
|
||||
#define IAX_COMMAND_LAGRP 12
|
||||
#define IAX_COMMAND_REGREQ 13 /* Registration request */
|
||||
#define IAX_COMMAND_REGAUTH 14 /* Registration authentication required */
|
||||
#define IAX_COMMAND_REGACK 15 /* Registration accepted */
|
||||
#define IAX_COMMAND_REGREJ 16 /* Registration rejected */
|
||||
#define IAX_COMMAND_REGREL 17 /* Force release of registration */
|
||||
#define IAX_COMMAND_VNAK 18 /* If we receive voice before valid first voice frame, send this */
|
||||
#define IAX_COMMAND_DPREQ 19 /* Request status of a dialplan entry */
|
||||
#define IAX_COMMAND_DPREP 20 /* Request status of a dialplan entry */
|
||||
#define IAX_COMMAND_DIAL 21 /* Request a dial on channel brought up TBD */
|
||||
#define IAX_COMMAND_TXREQ 22 /* Transfer Request */
|
||||
#define IAX_COMMAND_TXCNT 23 /* Transfer Connect */
|
||||
#define IAX_COMMAND_TXACC 24 /* Transfer Accepted */
|
||||
#define IAX_COMMAND_TXREADY 25 /* Transfer ready */
|
||||
#define IAX_COMMAND_TXREL 26 /* Transfer release */
|
||||
#define IAX_COMMAND_TXREJ 27 /* Transfer reject */
|
||||
#define IAX_COMMAND_QUELCH 28 /* Stop audio/video transmission */
|
||||
#define IAX_COMMAND_UNQUELCH 29 /* Resume audio/video transmission */
|
||||
|
||||
#define IAX_DEFAULT_REG_EXPIRE 60
|
||||
|
||||
#define IAX_DEFAULT_PORTNO 5036
|
||||
|
||||
/* Full frames are always delivered reliably */
|
||||
struct 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 iax_mini_hdr {
|
||||
short callno; /* Source call number -- high bit must be 0 */
|
||||
unsigned short ts; /* 16-bit Timestamp (high 16 bits from last IAX_full_hdr) */
|
||||
/* Frametype implicitly VOICE_FRAME */
|
||||
/* subclass implicit from last IAX_full_hdr */
|
||||
char data[0];
|
||||
};
|
||||
|
||||
#endif
|
||||
+822
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Implementation of Inter-Asterisk eXchange
|
||||
*
|
||||
* Copyright (C) 2003-2004, Digium
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*/
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#include "winpoop.h"
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "iax2.h"
|
||||
#include "iax2-parser.h"
|
||||
|
||||
static int frames = 0;
|
||||
static int iframes = 0;
|
||||
static int oframes = 0;
|
||||
|
||||
#ifdef ALIGN32
|
||||
static unsigned int get_uint32(unsigned char *p)
|
||||
{
|
||||
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
|
||||
}
|
||||
|
||||
static unsigned short get_uint16(unsigned char *p)
|
||||
{
|
||||
return (p[0] << 8) | p[1] ;
|
||||
}
|
||||
|
||||
#else
|
||||
#define get_uint32(p) (*((unsigned int *)(p)))
|
||||
#define get_uint16(p) (*((unsigned short *)(p)))
|
||||
#endif
|
||||
|
||||
|
||||
static void internaloutput(const char *str)
|
||||
{
|
||||
//printf(str);
|
||||
}
|
||||
|
||||
static void internalerror(const char *str)
|
||||
{
|
||||
fprintf(stderr, "WARNING: %s", str);
|
||||
}
|
||||
|
||||
static void (*outputf)(const char *str) = internaloutput;
|
||||
static void (*errorf)(const char *str) = internalerror;
|
||||
|
||||
static void dump_addr(char *output, int maxlen, void *value, int len)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
if (len == sizeof(sin)) {
|
||||
memcpy(&sin, value, len);
|
||||
snprintf(output, maxlen, "IPV4 %s:%d", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
||||
} else {
|
||||
snprintf(output, maxlen, "Invalid Address");
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_string(char *output, int maxlen, void *value, int len)
|
||||
{
|
||||
maxlen--;
|
||||
if (maxlen > len)
|
||||
maxlen = len;
|
||||
strncpy(output,(const char *)value, maxlen);
|
||||
output[maxlen] = '\0';
|
||||
}
|
||||
|
||||
static void dump_int(char *output, int maxlen, void *value, int len)
|
||||
{
|
||||
if (len == (int)sizeof(unsigned int))
|
||||
snprintf(output, maxlen, "%lu", (unsigned long)ntohl(get_uint32(value)));
|
||||
else
|
||||
snprintf(output, maxlen, "Invalid INT");
|
||||
}
|
||||
|
||||
static void dump_short(char *output, int maxlen, void *value, int len)
|
||||
{
|
||||
if (len == (int)sizeof(unsigned short))
|
||||
snprintf(output, maxlen, "%d", ntohs(get_uint16(value)));
|
||||
else
|
||||
snprintf(output, maxlen, "Invalid SHORT");
|
||||
}
|
||||
|
||||
static void dump_byte(char *output, int maxlen, void *value, int len)
|
||||
{
|
||||
if (len == (int)sizeof(unsigned char))
|
||||
snprintf(output, maxlen, "%d", *((unsigned char *)value));
|
||||
else
|
||||
snprintf(output, maxlen, "Invalid BYTE");
|
||||
}
|
||||
|
||||
static void dump_samprate(char *output, int maxlen, void *value, int len)
|
||||
{
|
||||
char tmp[256]="";
|
||||
int sr;
|
||||
if (len == (int)sizeof(unsigned short)) {
|
||||
sr = ntohs(*((unsigned short *)value));
|
||||
if (sr & IAX_RATE_8KHZ)
|
||||
strcat(tmp, ",8khz");
|
||||
if (sr & IAX_RATE_11KHZ)
|
||||
strcat(tmp, ",11.025khz");
|
||||
if (sr & IAX_RATE_16KHZ)
|
||||
strcat(tmp, ",16khz");
|
||||
if (sr & IAX_RATE_22KHZ)
|
||||
strcat(tmp, ",22.05khz");
|
||||
if (sr & IAX_RATE_44KHZ)
|
||||
strcat(tmp, ",44.1khz");
|
||||
if (sr & IAX_RATE_48KHZ)
|
||||
strcat(tmp, ",48khz");
|
||||
if (strlen(tmp))
|
||||
strncpy(output, &tmp[1], maxlen - 1);
|
||||
else
|
||||
strncpy(output, "None specified!\n", maxlen - 1);
|
||||
} else
|
||||
snprintf(output, maxlen, "Invalid SHORT");
|
||||
|
||||
}
|
||||
|
||||
static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len);
|
||||
static void dump_prov(char *output, int maxlen, void *value, int len)
|
||||
{
|
||||
dump_prov_ies(output, maxlen, (unsigned char *)value, len);
|
||||
}
|
||||
|
||||
static struct iax2_ie {
|
||||
int ie;
|
||||
char *name;
|
||||
void (*dump)(char *output, int maxlen, void *value, int len);
|
||||
} ies[] = {
|
||||
{ IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
|
||||
{ IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string },
|
||||
{ IAX_IE_CALLING_ANI, "ANI", dump_string },
|
||||
{ IAX_IE_CALLING_NAME, "CALLING NAME", dump_string },
|
||||
{ IAX_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
|
||||
{ IAX_IE_USERNAME, "USERNAME", dump_string },
|
||||
{ IAX_IE_PASSWORD, "PASSWORD", dump_string },
|
||||
{ IAX_IE_CAPABILITY, "CAPABILITY", dump_int },
|
||||
{ IAX_IE_FORMAT, "FORMAT", dump_int },
|
||||
{ IAX_IE_LANGUAGE, "LANGUAGE", dump_string },
|
||||
{ IAX_IE_VERSION, "VERSION", dump_short },
|
||||
{ IAX_IE_ADSICPE, "ADSICPE", dump_short },
|
||||
{ IAX_IE_DNID, "DNID", dump_string },
|
||||
{ IAX_IE_AUTHMETHODS, "AUTHMETHODS", dump_short },
|
||||
{ IAX_IE_CHALLENGE, "CHALLENGE", dump_string },
|
||||
{ IAX_IE_MD5_RESULT, "MD5 RESULT", dump_string },
|
||||
{ IAX_IE_RSA_RESULT, "RSA RESULT", dump_string },
|
||||
{ IAX_IE_APPARENT_ADDR, "APPARENT ADDRESS", dump_addr },
|
||||
{ IAX_IE_REFRESH, "REFRESH", dump_short },
|
||||
{ IAX_IE_DPSTATUS, "DIALPLAN STATUS", dump_short },
|
||||
{ IAX_IE_CALLNO, "CALL NUMBER", dump_short },
|
||||
{ IAX_IE_CAUSE, "CAUSE", dump_string },
|
||||
{ IAX_IE_IAX_UNKNOWN, "UNKNOWN IAX CMD", dump_byte },
|
||||
{ IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short },
|
||||
{ IAX_IE_AUTOANSWER, "AUTO ANSWER REQ" },
|
||||
{ IAX_IE_TRANSFERID, "TRANSFER ID", dump_int },
|
||||
{ IAX_IE_RDNIS, "REFERRING DNIS", dump_string },
|
||||
{ IAX_IE_PROVISIONING, "PROVISIONING", dump_prov },
|
||||
{ IAX_IE_AESPROVISIONING, "AES PROVISIONG" },
|
||||
{ IAX_IE_DATETIME, "DATE TIME", dump_int },
|
||||
{ IAX_IE_DEVICETYPE, "DEVICE TYPE", dump_string },
|
||||
{ IAX_IE_SERVICEIDENT, "SERVICE IDENT", dump_string },
|
||||
{ IAX_IE_FIRMWAREVER, "FIRMWARE VER", dump_short },
|
||||
{ IAX_IE_FWBLOCKDESC, "FW BLOCK DESC", dump_int },
|
||||
{ IAX_IE_FWBLOCKDATA, "FW BLOCK DATA" },
|
||||
{ IAX_IE_PROVVER, "PROVISIONG VER", dump_int },
|
||||
{ IAX_IE_CALLINGPRES, "CALLING PRESNTN", dump_byte },
|
||||
{ IAX_IE_CALLINGTON, "CALLING TYPEOFNUM", dump_byte },
|
||||
{ IAX_IE_CALLINGTNS, "CALLING TRANSITNET", dump_short },
|
||||
{ IAX_IE_SAMPLINGRATE, "SAMPLINGRATE", dump_samprate },
|
||||
{ IAX_IE_CODEC_PREFS, "CODEC_PREFS", dump_string },
|
||||
{ IAX_IE_RR_JITTER, "RR_JITTER", dump_int },
|
||||
{ IAX_IE_RR_LOSS, "RR_LOSS", dump_int },
|
||||
{ IAX_IE_RR_PKTS, "RR_PKTS", dump_int },
|
||||
{ IAX_IE_RR_DELAY, "RR_DELAY", dump_short },
|
||||
{ IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int },
|
||||
{ IAX_IE_RR_OOO, "RR_OOO", dump_int },
|
||||
};
|
||||
|
||||
const char *iax_ie2str(int ie)
|
||||
{
|
||||
int x;
|
||||
for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
|
||||
if (ies[x].ie == ie)
|
||||
return ies[x].name;
|
||||
}
|
||||
return "Unknown IE";
|
||||
}
|
||||
|
||||
|
||||
static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len)
|
||||
{
|
||||
int ielen;
|
||||
int ie;
|
||||
int found;
|
||||
char tmp[256];
|
||||
if (len < 2)
|
||||
return;
|
||||
strcpy(output, "\n");
|
||||
maxlen -= (int)strlen(output); output += strlen(output);
|
||||
while(len > 2) {
|
||||
ie = iedata[0];
|
||||
ielen = iedata[1];
|
||||
if (ielen + 2> len) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Total Prov IE length of %d bytes exceeds remaining prov frame length of %d bytes\n", ielen + 2, len);
|
||||
strncpy(output, tmp, maxlen - 1);
|
||||
maxlen -= (int)strlen(output); output += strlen(output);
|
||||
return;
|
||||
}
|
||||
found = 0;
|
||||
if (!found) {
|
||||
snprintf(tmp, (int)sizeof(tmp), " Unknown Prov IE %03d : Present\n", ie);
|
||||
strncpy(output, tmp, maxlen - 1);
|
||||
maxlen -= (int)strlen(output); output += strlen(output);
|
||||
}
|
||||
iedata += (2 + ielen);
|
||||
len -= (2 + ielen);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_ies(unsigned char *iedata, int len)
|
||||
{
|
||||
int ielen;
|
||||
int ie;
|
||||
int x;
|
||||
int found;
|
||||
char interp[1024];
|
||||
char tmp[1024];
|
||||
if (len < 2)
|
||||
return;
|
||||
while(len > 2) {
|
||||
ie = iedata[0];
|
||||
ielen = iedata[1];
|
||||
if (ielen + 2> len) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
|
||||
outputf(tmp);
|
||||
return;
|
||||
}
|
||||
found = 0;
|
||||
for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
|
||||
if (ies[x].ie == ie) {
|
||||
if (ies[x].dump) {
|
||||
ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
|
||||
snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp);
|
||||
outputf(tmp);
|
||||
} else {
|
||||
if (ielen)
|
||||
snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
|
||||
else
|
||||
strcpy(interp, "Present");
|
||||
snprintf(tmp, (int)sizeof(tmp), " %-15.15s : %s\n", ies[x].name, interp);
|
||||
outputf(tmp);
|
||||
}
|
||||
found++;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
snprintf(tmp, (int)sizeof(tmp), " Unknown IE %03d : Present\n", ie);
|
||||
outputf(tmp);
|
||||
}
|
||||
iedata += (2 + ielen);
|
||||
len -= (2 + ielen);
|
||||
}
|
||||
outputf("\n");
|
||||
}
|
||||
|
||||
void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
|
||||
{
|
||||
const char *frames[] = {
|
||||
"(0?)",
|
||||
"DTMF ",
|
||||
"VOICE ",
|
||||
"VIDEO ",
|
||||
"CONTROL",
|
||||
"NULL ",
|
||||
"IAX ",
|
||||
"TEXT ",
|
||||
"IMAGE " };
|
||||
const char *iaxs[] = {
|
||||
"(0?)",
|
||||
"NEW ",
|
||||
"PING ",
|
||||
"PONG ",
|
||||
"ACK ",
|
||||
"HANGUP ",
|
||||
"REJECT ",
|
||||
"ACCEPT ",
|
||||
"AUTHREQ",
|
||||
"AUTHREP",
|
||||
"INVAL ",
|
||||
"LAGRQ ",
|
||||
"LAGRP ",
|
||||
"REGREQ ",
|
||||
"REGAUTH",
|
||||
"REGACK ",
|
||||
"REGREJ ",
|
||||
"REGREL ",
|
||||
"VNAK ",
|
||||
"DPREQ ",
|
||||
"DPREP ",
|
||||
"DIAL ",
|
||||
"TXREQ ",
|
||||
"TXCNT ",
|
||||
"TXACC ",
|
||||
"TXREADY",
|
||||
"TXREL ",
|
||||
"TXREJ ",
|
||||
"QUELCH ",
|
||||
"UNQULCH",
|
||||
"POKE",
|
||||
"PAGE",
|
||||
"MWI",
|
||||
"UNSUPPORTED",
|
||||
"TRANSFER",
|
||||
"PROVISION",
|
||||
"FWDOWNLD",
|
||||
"FWDATA"
|
||||
};
|
||||
const char *cmds[] = {
|
||||
"(0?)",
|
||||
"HANGUP ",
|
||||
"RING ",
|
||||
"RINGING",
|
||||
"ANSWER ",
|
||||
"BUSY ",
|
||||
"TKOFFHK ",
|
||||
"OFFHOOK ",
|
||||
"CONGESTION ",
|
||||
"FLASH ",
|
||||
"WINK ",
|
||||
"OPTION "
|
||||
};
|
||||
struct ast_iax2_full_hdr *fh;
|
||||
char retries[20];
|
||||
char class2[20];
|
||||
char subclass2[20];
|
||||
const char *clas;
|
||||
const char *subclass;
|
||||
char tmp[256];
|
||||
|
||||
if (f) {
|
||||
fh = (struct ast_iax2_full_hdr *)f->data;
|
||||
snprintf(retries, (int)sizeof(retries), "%03d", f->retries);
|
||||
} else {
|
||||
fh = fhi;
|
||||
if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
|
||||
strcpy(retries, "Yes");
|
||||
else
|
||||
strcpy(retries, " No");
|
||||
}
|
||||
if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
|
||||
/* Don't mess with mini-frames */
|
||||
return;
|
||||
}
|
||||
if (fh->type >= (int)(sizeof(frames)/sizeof(char *))) {
|
||||
snprintf(class2, (int)sizeof(class2), "(%d?)", fh->type);
|
||||
clas = class2;
|
||||
} else {
|
||||
clas = frames[(int)fh->type];
|
||||
}
|
||||
if (fh->type == AST_FRAME_DTMF) {
|
||||
sprintf(subclass2, "%c", fh->csub);
|
||||
subclass = subclass2;
|
||||
} else if (fh->type == AST_FRAME_IAX) {
|
||||
if (fh->csub >= (int)sizeof(iaxs)/(int)sizeof(iaxs[0])) {
|
||||
snprintf(subclass2, (int)sizeof(subclass2), "(%d?)", fh->csub);
|
||||
subclass = subclass2;
|
||||
} else {
|
||||
subclass = iaxs[(int)fh->csub];
|
||||
}
|
||||
} else if (fh->type == AST_FRAME_CONTROL) {
|
||||
if (fh->csub >= (int)(sizeof(cmds)/sizeof(char *))) {
|
||||
snprintf(subclass2, (int)sizeof(subclass2), "(%d?)", fh->csub);
|
||||
subclass = subclass2;
|
||||
} else {
|
||||
subclass = cmds[(int)fh->csub];
|
||||
}
|
||||
} else {
|
||||
snprintf(subclass2, (int)sizeof(subclass2), "%d", fh->csub);
|
||||
subclass = subclass2;
|
||||
}
|
||||
snprintf(tmp, (int)sizeof(tmp),
|
||||
"%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
|
||||
(rx ? "Rx" : "Tx"),
|
||||
retries, fh->oseqno, fh->iseqno, clas, subclass);
|
||||
outputf(tmp);
|
||||
snprintf(tmp, (int)sizeof(tmp),
|
||||
" Timestamp: %05lums SCall: %5.5d DCall: %5.5d [%s:%d]\n",
|
||||
(unsigned long)ntohl(fh->ts),
|
||||
ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
|
||||
inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
|
||||
outputf(tmp);
|
||||
if (fh->type == AST_FRAME_IAX)
|
||||
dump_ies(fh->iedata, datalen);
|
||||
}
|
||||
|
||||
int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
|
||||
{
|
||||
char tmp[256];
|
||||
if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", iax_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
|
||||
errorf(tmp);
|
||||
return -1;
|
||||
}
|
||||
ied->buf[ied->pos++] = ie;
|
||||
ied->buf[ied->pos++] = datalen;
|
||||
memcpy(ied->buf + ied->pos, data, datalen);
|
||||
ied->pos += datalen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
|
||||
{
|
||||
return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
|
||||
{
|
||||
unsigned int newval;
|
||||
newval = htonl(value);
|
||||
return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
|
||||
}
|
||||
|
||||
int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
|
||||
{
|
||||
unsigned short newval;
|
||||
newval = htons(value);
|
||||
return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
|
||||
}
|
||||
|
||||
int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str)
|
||||
{
|
||||
return iax_ie_append_raw(ied, ie, str, (int)strlen(str));
|
||||
}
|
||||
|
||||
int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
|
||||
{
|
||||
return iax_ie_append_raw(ied, ie, &dat, 1);
|
||||
}
|
||||
|
||||
int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
|
||||
{
|
||||
return iax_ie_append_raw(ied, ie, NULL, 0);
|
||||
}
|
||||
|
||||
void iax_set_output(void (*func)(const char *))
|
||||
{
|
||||
outputf = func;
|
||||
}
|
||||
|
||||
void iax_set_error(void (*func)(const char *))
|
||||
{
|
||||
errorf = func;
|
||||
}
|
||||
|
||||
int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
|
||||
{
|
||||
/* Parse data into information elements */
|
||||
int len;
|
||||
int ie;
|
||||
char tmp[256];
|
||||
memset(ies, 0, (int)sizeof(struct iax_ies));
|
||||
ies->msgcount = -1;
|
||||
ies->firmwarever = -1;
|
||||
ies->calling_ton = -1;
|
||||
ies->calling_tns = -1;
|
||||
ies->calling_pres = -1;
|
||||
ies->samprate = IAX_RATE_8KHZ;
|
||||
while(datalen >= 2) {
|
||||
ie = data[0];
|
||||
len = data[1];
|
||||
if (len > datalen - 2) {
|
||||
errorf("Information element length exceeds message size\n");
|
||||
return -1;
|
||||
}
|
||||
switch(ie) {
|
||||
case IAX_IE_CALLED_NUMBER:
|
||||
ies->called_number = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_CALLING_NUMBER:
|
||||
ies->calling_number = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_CALLING_ANI:
|
||||
ies->calling_ani = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_CALLING_NAME:
|
||||
ies->calling_name = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_CALLED_CONTEXT:
|
||||
ies->called_context = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_USERNAME:
|
||||
ies->username = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_PASSWORD:
|
||||
ies->password = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_CAPABILITY:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->capability = ntohl(get_uint32(data + 2));
|
||||
break;
|
||||
case IAX_IE_FORMAT:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->format = ntohl(get_uint32(data + 2));
|
||||
break;
|
||||
case IAX_IE_LANGUAGE:
|
||||
ies->language = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_CODEC_PREFS:
|
||||
ies->codec_prefs = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_VERSION:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->version = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_ADSICPE:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->adsicpe = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_SAMPLINGRATE:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->samprate = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_DNID:
|
||||
ies->dnid = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_RDNIS:
|
||||
ies->rdnis = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_AUTHMETHODS:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->authmethods = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_CHALLENGE:
|
||||
ies->challenge = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_MD5_RESULT:
|
||||
ies->md5_result = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_RSA_RESULT:
|
||||
ies->rsa_result = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_APPARENT_ADDR:
|
||||
ies->apparent_addr = ((struct sockaddr_in *)(data + 2));
|
||||
break;
|
||||
case IAX_IE_REFRESH:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->refresh = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_DPSTATUS:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->dpstatus = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_CALLNO:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->callno = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_CAUSE:
|
||||
ies->cause = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_CAUSECODE:
|
||||
if (len != 1) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
|
||||
errorf(tmp);
|
||||
} else {
|
||||
ies->causecode = data[2];
|
||||
}
|
||||
break;
|
||||
case IAX_IE_IAX_UNKNOWN:
|
||||
if (len == 1)
|
||||
ies->iax_unknown = data[2];
|
||||
else {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
|
||||
errorf(tmp);
|
||||
}
|
||||
break;
|
||||
case IAX_IE_MSGCOUNT:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->msgcount = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_AUTOANSWER:
|
||||
ies->autoanswer = 1;
|
||||
break;
|
||||
case IAX_IE_MUSICONHOLD:
|
||||
ies->musiconhold = 1;
|
||||
break;
|
||||
case IAX_IE_TRANSFERID:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->transferid = ntohl(get_uint32(data + 2));
|
||||
break;
|
||||
case IAX_IE_DATETIME:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->datetime = ntohl(get_uint32(data + 2));
|
||||
break;
|
||||
case IAX_IE_FIRMWAREVER:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->firmwarever = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_DEVICETYPE:
|
||||
ies->devicetype = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_SERVICEIDENT:
|
||||
ies->serviceident = (char *) data + 2;
|
||||
break;
|
||||
case IAX_IE_FWBLOCKDESC:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->fwdesc = ntohl(get_uint32(data + 2));
|
||||
break;
|
||||
case IAX_IE_FWBLOCKDATA:
|
||||
ies->fwdata = data + 2;
|
||||
ies->fwdatalen = len;
|
||||
break;
|
||||
case IAX_IE_PROVVER:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else {
|
||||
ies->provverpres = 1;
|
||||
ies->provver = ntohl(get_uint32(data + 2));
|
||||
}
|
||||
break;
|
||||
case IAX_IE_CALLINGPRES:
|
||||
if (len == 1)
|
||||
ies->calling_pres = data[2];
|
||||
else {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
|
||||
errorf(tmp);
|
||||
}
|
||||
break;
|
||||
case IAX_IE_CALLINGTON:
|
||||
if (len == 1)
|
||||
ies->calling_ton = data[2];
|
||||
else {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
|
||||
errorf(tmp);
|
||||
}
|
||||
break;
|
||||
case IAX_IE_CALLINGTNS:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else
|
||||
ies->calling_tns = ntohs(get_uint16(data + 2));
|
||||
break;
|
||||
case IAX_IE_RR_JITTER:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else {
|
||||
ies->rr_jitter = ntohl(get_uint32(data + 2));
|
||||
}
|
||||
break;
|
||||
case IAX_IE_RR_LOSS:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else {
|
||||
ies->rr_loss = ntohl(get_uint32(data + 2));
|
||||
}
|
||||
break;
|
||||
case IAX_IE_RR_PKTS:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else {
|
||||
ies->rr_pkts = ntohl(get_uint32(data + 2));
|
||||
}
|
||||
break;
|
||||
case IAX_IE_RR_DELAY:
|
||||
if (len != (int)sizeof(unsigned short)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||
errorf(tmp);
|
||||
} else {
|
||||
ies->rr_delay = ntohs(get_uint16(data + 2));
|
||||
}
|
||||
break;
|
||||
case IAX_IE_RR_DROPPED:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else {
|
||||
ies->rr_dropped = ntohl(get_uint32(data + 2));
|
||||
}
|
||||
break;
|
||||
case IAX_IE_RR_OOO:
|
||||
if (len != (int)sizeof(unsigned int)) {
|
||||
snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||
errorf(tmp);
|
||||
} else {
|
||||
ies->rr_ooo = ntohl(get_uint32(data + 2));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
|
||||
outputf(tmp);
|
||||
}
|
||||
/* Overwrite information element with 0, to null terminate previous portion */
|
||||
data[0] = 0;
|
||||
datalen -= (len + 2);
|
||||
data += (len + 2);
|
||||
}
|
||||
/* Null-terminate last field */
|
||||
*data = '\0';
|
||||
if (datalen) {
|
||||
errorf("Invalid information element contents, strange boundary\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
|
||||
{
|
||||
fr->af.frametype = f->frametype;
|
||||
fr->af.subclass = f->subclass;
|
||||
fr->af.mallocd = 0; /* Our frame is static relative to the container */
|
||||
fr->af.datalen = f->datalen;
|
||||
fr->af.samples = f->samples;
|
||||
fr->af.offset = AST_FRIENDLY_OFFSET;
|
||||
fr->af.src = f->src;
|
||||
fr->af.data = fr->afdata;
|
||||
if (fr->af.datalen)
|
||||
memcpy(fr->af.data, f->data, fr->af.datalen);
|
||||
}
|
||||
|
||||
struct iax_frame *iax_frame_new(int direction, int datalen)
|
||||
{
|
||||
struct iax_frame *fr;
|
||||
fr = (struct iax_frame *)malloc((int)sizeof(struct iax_frame) + datalen);
|
||||
if (fr) {
|
||||
fr->direction = direction;
|
||||
fr->retrans = -1;
|
||||
frames++;
|
||||
if (fr->direction == DIRECTION_INGRESS)
|
||||
iframes++;
|
||||
else
|
||||
oframes++;
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
void iax_frame_free(struct iax_frame *fr)
|
||||
{
|
||||
/* Note: does not remove from scheduler! */
|
||||
if (fr->direction == DIRECTION_INGRESS)
|
||||
iframes--;
|
||||
else if (fr->direction == DIRECTION_OUTGRESS)
|
||||
oframes--;
|
||||
else {
|
||||
errorf("Attempt to double free frame detected\n");
|
||||
return;
|
||||
}
|
||||
fr->direction = 0;
|
||||
free(fr);
|
||||
frames--;
|
||||
}
|
||||
|
||||
int iax_get_frames(void) { return frames; }
|
||||
int iax_get_iframes(void) { return iframes; }
|
||||
int iax_get_oframes(void) { return oframes; }
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Implementation of Inter-Asterisk eXchange
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*/
|
||||
|
||||
#ifndef _IAX2_PARSER_H
|
||||
#define _IAX2_PARSER_H
|
||||
|
||||
struct iax_ies {
|
||||
char *called_number;
|
||||
char *calling_number;
|
||||
char *calling_ani;
|
||||
char *calling_name;
|
||||
int calling_ton;
|
||||
int calling_tns;
|
||||
int calling_pres;
|
||||
char *called_context;
|
||||
char *username;
|
||||
char *password;
|
||||
unsigned int capability;
|
||||
unsigned int format;
|
||||
char *codec_prefs;
|
||||
char *language;
|
||||
int version;
|
||||
unsigned short adsicpe;
|
||||
char *dnid;
|
||||
char *rdnis;
|
||||
unsigned int authmethods;
|
||||
char *challenge;
|
||||
char *md5_result;
|
||||
char *rsa_result;
|
||||
struct sockaddr_in *apparent_addr;
|
||||
unsigned short refresh;
|
||||
unsigned short dpstatus;
|
||||
unsigned short callno;
|
||||
char *cause;
|
||||
unsigned char causecode;
|
||||
unsigned char iax_unknown;
|
||||
int msgcount;
|
||||
int autoanswer;
|
||||
int musiconhold;
|
||||
unsigned int transferid;
|
||||
unsigned int datetime;
|
||||
char *devicetype;
|
||||
char *serviceident;
|
||||
int firmwarever;
|
||||
unsigned int fwdesc;
|
||||
unsigned char *fwdata;
|
||||
unsigned char fwdatalen;
|
||||
unsigned int provver;
|
||||
unsigned short samprate;
|
||||
unsigned int provverpres;
|
||||
unsigned int rr_jitter;
|
||||
unsigned int rr_loss;
|
||||
unsigned int rr_pkts;
|
||||
unsigned short rr_delay;
|
||||
unsigned int rr_dropped;
|
||||
unsigned int rr_ooo;
|
||||
};
|
||||
|
||||
#define DIRECTION_INGRESS 1
|
||||
#define DIRECTION_OUTGRESS 2
|
||||
|
||||
struct iax_frame {
|
||||
#ifdef LIBIAX
|
||||
struct iax_session *session;
|
||||
struct iax_event *event;
|
||||
#endif
|
||||
|
||||
/* /Our/ call number */
|
||||
unsigned short callno;
|
||||
/* /Their/ call number */
|
||||
unsigned short dcallno;
|
||||
/* Start of raw frame (outgoing only) */
|
||||
void *data;
|
||||
/* Length of frame (outgoing only) */
|
||||
int datalen;
|
||||
/* How many retries so far? */
|
||||
int retries;
|
||||
/* Outgoing relative timestamp (ms) */
|
||||
unsigned int ts;
|
||||
/* How long to wait before retrying */
|
||||
int retrytime;
|
||||
/* Are we received out of order? */
|
||||
int outoforder;
|
||||
/* Have we been sent at all yet? */
|
||||
int sentyet;
|
||||
/* Outgoing Packet sequence number */
|
||||
int oseqno;
|
||||
/* Next expected incoming packet sequence number */
|
||||
int iseqno;
|
||||
/* Non-zero if should be sent to transfer peer */
|
||||
int transfer;
|
||||
/* Non-zero if this is the final message */
|
||||
int final;
|
||||
/* Ingress or outgres */
|
||||
int direction;
|
||||
/* Retransmission ID */
|
||||
int retrans;
|
||||
/* Easy linking */
|
||||
struct iax_frame *next;
|
||||
struct iax_frame *prev;
|
||||
/* Actual, isolated frame header */
|
||||
struct ast_frame af;
|
||||
unsigned char unused[AST_FRIENDLY_OFFSET];
|
||||
unsigned char afdata[0]; /* Data for frame */
|
||||
};
|
||||
|
||||
struct iax_ie_data {
|
||||
unsigned char buf[1024];
|
||||
int pos;
|
||||
};
|
||||
|
||||
/* Choose a different function for output */
|
||||
extern void iax_set_output(void (*output)(const char *data));
|
||||
/* Choose a different function for errors */
|
||||
extern void iax_set_error(void (*output)(const char *data));
|
||||
extern void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen);
|
||||
|
||||
extern const char *iax_ie2str(int ie);
|
||||
|
||||
extern int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen);
|
||||
extern int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, struct sockaddr_in *sin);
|
||||
extern int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value);
|
||||
extern int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value);
|
||||
extern int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, const char *str);
|
||||
extern int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat);
|
||||
extern int iax_ie_append(struct iax_ie_data *ied, unsigned char ie);
|
||||
extern int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen);
|
||||
|
||||
extern int iax_get_frames(void);
|
||||
extern int iax_get_iframes(void);
|
||||
extern int iax_get_oframes(void);
|
||||
|
||||
extern void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f);
|
||||
extern struct iax_frame *iax_frame_new(int direction, int datalen);
|
||||
extern void iax_frame_free(struct iax_frame *fr);
|
||||
#endif
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Implementation of Inter-Asterisk eXchange
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*/
|
||||
|
||||
#ifndef _IAX2_H
|
||||
#define _IAX2_H
|
||||
|
||||
/* Max version of IAX protocol we support */
|
||||
#define IAX_PROTO_VERSION 2
|
||||
|
||||
#define IAX_MAX_CALLS 32768
|
||||
|
||||
#define IAX_FLAG_FULL 0x8000
|
||||
|
||||
#define IAX_FLAG_RETRANS 0x8000
|
||||
|
||||
#define IAX_FLAG_SC_LOG 0x80
|
||||
|
||||
#define IAX_MAX_SHIFT 0x1F
|
||||
|
||||
#define IAX_WINDOW 64
|
||||
|
||||
/* Subclass for AST_FRAME_IAX */
|
||||
#define IAX_COMMAND_NEW 1
|
||||
#define IAX_COMMAND_PING 2
|
||||
#define IAX_COMMAND_PONG 3
|
||||
#define IAX_COMMAND_ACK 4
|
||||
#define IAX_COMMAND_HANGUP 5
|
||||
#define IAX_COMMAND_REJECT 6
|
||||
#define IAX_COMMAND_ACCEPT 7
|
||||
#define IAX_COMMAND_AUTHREQ 8
|
||||
#define IAX_COMMAND_AUTHREP 9
|
||||
#define IAX_COMMAND_INVAL 10
|
||||
#define IAX_COMMAND_LAGRQ 11
|
||||
#define IAX_COMMAND_LAGRP 12
|
||||
#define IAX_COMMAND_REGREQ 13 /* Registration request */
|
||||
#define IAX_COMMAND_REGAUTH 14 /* Registration authentication required */
|
||||
#define IAX_COMMAND_REGACK 15 /* Registration accepted */
|
||||
#define IAX_COMMAND_REGREJ 16 /* Registration rejected */
|
||||
#define IAX_COMMAND_REGREL 17 /* Force release of registration */
|
||||
#define IAX_COMMAND_VNAK 18 /* If we receive voice before valid first voice frame, send this */
|
||||
#define IAX_COMMAND_DPREQ 19 /* Request status of a dialplan entry */
|
||||
#define IAX_COMMAND_DPREP 20 /* Request status of a dialplan entry */
|
||||
#define IAX_COMMAND_DIAL 21 /* Request a dial on channel brought up TBD */
|
||||
#define IAX_COMMAND_TXREQ 22 /* Transfer Request */
|
||||
#define IAX_COMMAND_TXCNT 23 /* Transfer Connect */
|
||||
#define IAX_COMMAND_TXACC 24 /* Transfer Accepted */
|
||||
#define IAX_COMMAND_TXREADY 25 /* Transfer ready */
|
||||
#define IAX_COMMAND_TXREL 26 /* Transfer release */
|
||||
#define IAX_COMMAND_TXREJ 27 /* Transfer reject */
|
||||
#define IAX_COMMAND_QUELCH 28 /* Stop audio/video transmission */
|
||||
#define IAX_COMMAND_UNQUELCH 29 /* Resume audio/video transmission */
|
||||
#define IAX_COMMAND_POKE 30 /* Like ping, but does not require an open connection */
|
||||
#define IAX_COMMAND_PAGE 31 /* Paging description */
|
||||
#define IAX_COMMAND_MWI 32 /* Stand-alone message waiting indicator */
|
||||
#define IAX_COMMAND_UNSUPPORT 33 /* Unsupported message received */
|
||||
#define IAX_COMMAND_TRANSFER 34 /* Request remote transfer */
|
||||
#define IAX_COMMAND_PROVISION 35 /* Provision device */
|
||||
#define IAX_COMMAND_FWDOWNL 36 /* Download firmware */
|
||||
#define IAX_COMMAND_FWDATA 37 /* Firmware Data */
|
||||
|
||||
#define IAX_DEFAULT_REG_EXPIRE 60 /* By default require re-registration once per minute */
|
||||
|
||||
#define IAX_LINGER_TIMEOUT 10 /* How long to wait before closing bridged call */
|
||||
|
||||
#define IAX_DEFAULT_PORTNO 4569
|
||||
|
||||
/* IAX Information elements */
|
||||
#define IAX_IE_CALLED_NUMBER 1 /* Number/extension being called - string */
|
||||
#define IAX_IE_CALLING_NUMBER 2 /* Calling number - string */
|
||||
#define IAX_IE_CALLING_ANI 3 /* Calling number ANI for billing - string */
|
||||
#define IAX_IE_CALLING_NAME 4 /* Name of caller - string */
|
||||
#define IAX_IE_CALLED_CONTEXT 5 /* Context for number - string */
|
||||
#define IAX_IE_USERNAME 6 /* Username (peer or user) for authentication - string */
|
||||
#define IAX_IE_PASSWORD 7 /* Password for authentication - string */
|
||||
#define IAX_IE_CAPABILITY 8 /* Actual codec capability - unsigned int */
|
||||
#define IAX_IE_FORMAT 9 /* Desired codec format - unsigned int */
|
||||
#define IAX_IE_LANGUAGE 10 /* Desired language - string */
|
||||
#define IAX_IE_VERSION 11 /* Protocol version - short */
|
||||
#define IAX_IE_ADSICPE 12 /* CPE ADSI capability - short */
|
||||
#define IAX_IE_DNID 13 /* Originally dialed DNID - string */
|
||||
#define IAX_IE_AUTHMETHODS 14 /* Authentication method(s) - short */
|
||||
#define IAX_IE_CHALLENGE 15 /* Challenge data for MD5/RSA - string */
|
||||
#define IAX_IE_MD5_RESULT 16 /* MD5 challenge result - string */
|
||||
#define IAX_IE_RSA_RESULT 17 /* RSA challenge result - string */
|
||||
#define IAX_IE_APPARENT_ADDR 18 /* Apparent address of peer - struct sockaddr_in */
|
||||
#define IAX_IE_REFRESH 19 /* When to refresh registration - short */
|
||||
#define IAX_IE_DPSTATUS 20 /* Dialplan status - short */
|
||||
#define IAX_IE_CALLNO 21 /* Call number of peer - short */
|
||||
#define IAX_IE_CAUSE 22 /* Cause - string */
|
||||
#define IAX_IE_IAX_UNKNOWN 23 /* Unknown IAX command - byte */
|
||||
#define IAX_IE_MSGCOUNT 24 /* How many messages waiting - short */
|
||||
#define IAX_IE_AUTOANSWER 25 /* Request auto-answering -- none */
|
||||
#define IAX_IE_MUSICONHOLD 26 /* Request musiconhold with QUELCH -- none or string */
|
||||
#define IAX_IE_TRANSFERID 27 /* Transfer Request Identifier -- int */
|
||||
#define IAX_IE_RDNIS 28 /* Referring DNIS -- string */
|
||||
#define IAX_IE_PROVISIONING 29 /* Provisioning info */
|
||||
#define IAX_IE_AESPROVISIONING 30 /* AES Provisioning info */
|
||||
#define IAX_IE_DATETIME 31 /* Date/Time */
|
||||
#define IAX_IE_DEVICETYPE 32 /* Device Type -- string */
|
||||
#define IAX_IE_SERVICEIDENT 33 /* Service Identifier -- string */
|
||||
#define IAX_IE_FIRMWAREVER 34 /* Firmware revision -- u16 */
|
||||
#define IAX_IE_FWBLOCKDESC 35 /* Firmware block description -- u32 */
|
||||
#define IAX_IE_FWBLOCKDATA 36 /* Firmware block of data -- raw */
|
||||
#define IAX_IE_PROVVER 37 /* Provisioning Version (u32) */
|
||||
#define IAX_IE_CALLINGPRES 38 /* Calling presentation (u8) */
|
||||
#define IAX_IE_CALLINGTON 39 /* Calling type of number (u8) */
|
||||
#define IAX_IE_CALLINGTNS 40 /* Calling transit network select (u16) */
|
||||
#define IAX_IE_SAMPLINGRATE 41 /* Supported sampling rates (u16) */
|
||||
#define IAX_IE_CAUSECODE 42 /* Hangup cause (u8) */
|
||||
#define IAX_IE_ENCRYPTION 43 /* Encryption format (u16) */
|
||||
#define IAX_IE_ENCKEY 44 /* Encryption key (raw) */
|
||||
#define IAX_IE_CODEC_PREFS 45 /* Codec Negotiation */
|
||||
|
||||
#define IAX_IE_RR_JITTER 46 /* Received jitter (as in RFC1889) u32 */
|
||||
#define IAX_IE_RR_LOSS 47 /* Received loss (high byte loss pct, low 24 bits loss count, as in rfc1889 */
|
||||
#define IAX_IE_RR_PKTS 48 /* Received frames (total frames received) u32 */
|
||||
#define IAX_IE_RR_DELAY 49 /* Max playout delay for received frames (in ms) u16 */
|
||||
#define IAX_IE_RR_DROPPED 50 /* Dropped frames (presumably by jitterbuf) u32 */
|
||||
#define IAX_IE_RR_OOO 51 /* Frames received Out of Order u32 */
|
||||
|
||||
|
||||
|
||||
#define IAX_AUTH_PLAINTEXT (1 << 0)
|
||||
#define IAX_AUTH_MD5 (1 << 1)
|
||||
#define IAX_AUTH_RSA (1 << 2)
|
||||
|
||||
#define IAX_META_TRUNK 1 /* Trunk meta-message */
|
||||
#define IAX_META_VIDEO 2 /* Video frame */
|
||||
|
||||
#define IAX_RATE_8KHZ (1 << 0) /* 8khz sampling (default if absent) */
|
||||
#define IAX_RATE_11KHZ (1 << 1) /* 11.025khz sampling */
|
||||
#define IAX_RATE_16KHZ (1 << 2) /* 16khz sampling */
|
||||
#define IAX_RATE_22KHZ (1 << 3) /* 22.05khz sampling */
|
||||
#define IAX_RATE_44KHZ (1 << 4) /* 44.1khz sampling */
|
||||
#define IAX_RATE_48KHZ (1 << 5) /* 48khz sampling */
|
||||
|
||||
#define IAX_DPSTATUS_EXISTS (1 << 0)
|
||||
#define IAX_DPSTATUS_CANEXIST (1 << 1)
|
||||
#define IAX_DPSTATUS_NONEXISTANT (1 << 2)
|
||||
#define IAX_DPSTATUS_IGNOREPAT (1 << 14)
|
||||
#define IAX_DPSTATUS_MATCHMORE (1 << 15)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(push,1)
|
||||
#define __PACKED
|
||||
#else
|
||||
#define __PACKED __attribute__ ((__packed__))
|
||||
#endif
|
||||
|
||||
/* Full frames are always delivered reliably */
|
||||
struct ast_iax2_full_hdr {
|
||||
unsigned short scallno; /* Source call number -- high bit must be 1 */
|
||||
unsigned short dcallno; /* Destination call number -- high bit is 1 if retransmission */
|
||||
unsigned int ts; /* 32-bit timestamp in milliseconds (from 1st transmission) */
|
||||
unsigned char oseqno; /* Packet number (outgoing) */
|
||||
unsigned char iseqno; /* Packet number (next incoming expected) */
|
||||
char type; /* Frame type */
|
||||
unsigned char csub; /* Compressed subclass */
|
||||
unsigned char iedata[0];
|
||||
} __PACKED;
|
||||
|
||||
/* Mini header is used only for voice frames -- delivered unreliably */
|
||||
struct ast_iax2_mini_hdr {
|
||||
unsigned short callno; /* Source call number -- high bit must be 0, rest must be non-zero */
|
||||
unsigned short ts; /* 16-bit Timestamp (high 16 bits from last ast_iax2_full_hdr) */
|
||||
/* Frametype implicitly VOICE_FRAME */
|
||||
/* subclass implicit from last ast_iax2_full_hdr */
|
||||
unsigned char data[0];
|
||||
} __PACKED;
|
||||
|
||||
struct ast_iax2_meta_hdr {
|
||||
unsigned short zeros; /* Zeros field -- must be zero */
|
||||
unsigned char metacmd; /* Meta command */
|
||||
unsigned char cmddata; /* Command Data */
|
||||
unsigned char data[0];
|
||||
} __PACKED;
|
||||
|
||||
struct ast_iax2_video_hdr {
|
||||
unsigned short zeros; /* Zeros field -- must be zero */
|
||||
unsigned short callno; /* Video call number */
|
||||
unsigned short ts; /* Timestamp and mark if present */
|
||||
unsigned char data[0];
|
||||
} __PACKED;
|
||||
|
||||
struct ast_iax2_meta_trunk_hdr {
|
||||
unsigned int ts; /* 32-bit timestamp for all messages */
|
||||
unsigned char data[0];
|
||||
} __PACKED;
|
||||
|
||||
struct ast_iax2_meta_trunk_entry {
|
||||
unsigned short callno; /* Call number */
|
||||
unsigned short len; /* Length of data for this callno */
|
||||
} __PACKED;
|
||||
|
||||
#define IAX_FIRMWARE_MAGIC 0x69617879
|
||||
|
||||
struct ast_iax2_firmware_header {
|
||||
unsigned int magic; /* Magic number */
|
||||
unsigned short version; /* Software version */
|
||||
unsigned char devname[16]; /* Device */
|
||||
unsigned int datalen; /* Data length of file beyond header */
|
||||
unsigned char chksum[16]; /* Checksum of all data */
|
||||
unsigned char data[0];
|
||||
} __PACKED;
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#undef __PACKED
|
||||
|
||||
#endif
|
||||
+833
@@ -0,0 +1,833 @@
|
||||
/*
|
||||
* jitterbuf: an application-independent jitterbuffer
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2004-2005, Horizon Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*
|
||||
* Copyright on this file is disclaimed to Digium for inclusion in Asterisk
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "jitterbuf.h"
|
||||
|
||||
/* define these here, just for ancient compiler systems */
|
||||
#define JB_LONGMAX 2147483647L
|
||||
#define JB_LONGMIN (-JB_LONGMAX - 1L)
|
||||
|
||||
/* MS VC can't do __VA_ARGS__ */
|
||||
#if (defined(WIN32) || defined(_WIN32_WCE)) && defined(_MSC_VER)
|
||||
#define jb_warn if (warnf) warnf
|
||||
#define jb_err if (errf) errf
|
||||
#define jb_dbg if (dbgf) dbgf
|
||||
|
||||
#ifdef DEEP_DEBUG
|
||||
#define jb_dbg2 if (dbgf) dbgf
|
||||
#else
|
||||
#define jb_dbg2 if (0) dbgf
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0)
|
||||
#define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0)
|
||||
#define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
|
||||
|
||||
#ifdef DEEP_DEBUG
|
||||
#define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
|
||||
#else
|
||||
#define jb_dbg2(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static jb_output_function_t warnf, errf, dbgf;
|
||||
|
||||
void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)
|
||||
{
|
||||
errf = err;
|
||||
warnf = warn;
|
||||
dbgf = dbg;
|
||||
}
|
||||
|
||||
static void increment_losspct(jitterbuf *jb)
|
||||
{
|
||||
jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;
|
||||
}
|
||||
|
||||
static void decrement_losspct(jitterbuf *jb)
|
||||
{
|
||||
jb->info.losspct = (499 * jb->info.losspct)/500;
|
||||
}
|
||||
|
||||
void jb_reset(jitterbuf *jb)
|
||||
{
|
||||
/* only save settings */
|
||||
jb_conf s = jb->info.conf;
|
||||
memset(jb, 0, sizeof(*jb));
|
||||
jb->info.conf = s;
|
||||
|
||||
/* initialize length, using the configured value */
|
||||
jb->info.current = jb->info.target = jb->info.conf.target_extra;
|
||||
jb->info.silence_begin_ts = -1;
|
||||
}
|
||||
|
||||
jitterbuf * jb_new()
|
||||
{
|
||||
jitterbuf *jb;
|
||||
|
||||
if (!(jb = (jitterbuf *)malloc(sizeof(*jb))))
|
||||
return NULL;
|
||||
|
||||
jb->info.conf.target_extra = JB_TARGET_EXTRA;
|
||||
|
||||
jb_reset(jb);
|
||||
|
||||
jb_dbg2("jb_new() = %x\n", jb);
|
||||
return jb;
|
||||
}
|
||||
|
||||
void jb_destroy(jitterbuf *jb)
|
||||
{
|
||||
jb_frame *frame;
|
||||
jb_dbg2("jb_destroy(%x)\n", jb);
|
||||
|
||||
/* free all the frames on the "free list" */
|
||||
frame = jb->free;
|
||||
while (frame != NULL) {
|
||||
jb_frame *next = frame->next;
|
||||
free(frame);
|
||||
frame = next;
|
||||
}
|
||||
|
||||
/* free ourselves! */
|
||||
free(jb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
static int longcmp(const void *a, const void *b)
|
||||
{
|
||||
return *(long *)a - *(long *)b;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* simple history manipulation */
|
||||
/* maybe later we can make the history buckets variable size, or something? */
|
||||
/* drop parameter determines whether we will drop outliers to minimize
|
||||
* delay */
|
||||
static int history_put(jitterbuf *jb, long ts, long now, long ms)
|
||||
{
|
||||
long delay = now - (ts - jb->info.resync_offset);
|
||||
long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold;
|
||||
long kicked;
|
||||
|
||||
/* don't add special/negative times to history */
|
||||
if (ts <= 0)
|
||||
return 0;
|
||||
|
||||
/* check for drastic change in delay */
|
||||
if (jb->info.conf.resync_threshold != -1) {
|
||||
if (labs(delay - jb->info.last_delay) > threshold) {
|
||||
jb->info.cnt_delay_discont++;
|
||||
if (jb->info.cnt_delay_discont > 3) {
|
||||
/* resync the jitterbuffer */
|
||||
jb->info.cnt_delay_discont = 0;
|
||||
jb->hist_ptr = 0;
|
||||
jb->hist_maxbuf_valid = 0;
|
||||
|
||||
jb_warn("Resyncing the jb. last_delay %ld, this delay %ld, threshold %ld, new offset %ld\n", jb->info.last_delay, delay, threshold, ts - now);
|
||||
jb->info.resync_offset = ts - now;
|
||||
jb->info.last_delay = delay = 0; /* after resync, frame is right on time */
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
jb->info.last_delay = delay;
|
||||
jb->info.cnt_delay_discont = 0;
|
||||
}
|
||||
}
|
||||
|
||||
kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ];
|
||||
|
||||
jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay;
|
||||
|
||||
/* optimization; the max/min buffers don't need to be recalculated,
|
||||
* if this packet's entry doesn't change them. This happens if this
|
||||
* packet is not involved, _and_ any packet that got kicked out of
|
||||
* the history is also not involved. We do a number of comparisons,
|
||||
* but it's probably still worthwhile, because it will usually
|
||||
* succeed, and should be a lot faster than going through all 500
|
||||
* packets in history */
|
||||
if (!jb->hist_maxbuf_valid)
|
||||
return 0;
|
||||
|
||||
/* don't do this until we've filled history
|
||||
* (reduces some edge cases below) */
|
||||
if (jb->hist_ptr < JB_HISTORY_SZ)
|
||||
goto invalidate;
|
||||
|
||||
/* if the new delay would go into min */
|
||||
if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
|
||||
goto invalidate;
|
||||
|
||||
/* or max.. */
|
||||
if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
|
||||
goto invalidate;
|
||||
|
||||
/* or the kicked delay would be in min */
|
||||
if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
|
||||
goto invalidate;
|
||||
|
||||
if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
|
||||
goto invalidate;
|
||||
|
||||
/* if we got here, we don't need to invalidate, 'cause this delay didn't
|
||||
* affect things */
|
||||
return 0;
|
||||
/* end optimization */
|
||||
|
||||
|
||||
invalidate:
|
||||
jb->hist_maxbuf_valid = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void history_calc_maxbuf(jitterbuf *jb)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
if (jb->hist_ptr == 0)
|
||||
return;
|
||||
|
||||
|
||||
/* initialize maxbuf/minbuf to the latest value */
|
||||
for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
|
||||
/*
|
||||
* jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
|
||||
* jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
|
||||
*/
|
||||
jb->hist_maxbuf[i] = JB_LONGMIN;
|
||||
jb->hist_minbuf[i] = JB_LONGMAX;
|
||||
}
|
||||
|
||||
/* use insertion sort to populate maxbuf */
|
||||
/* we want it to be the top "n" values, in order */
|
||||
|
||||
/* start at the beginning, or JB_HISTORY_SZ frames ago */
|
||||
i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0;
|
||||
|
||||
for (;i<jb->hist_ptr;i++) {
|
||||
long toins = jb->history[i % JB_HISTORY_SZ];
|
||||
|
||||
/* if the maxbuf should get this */
|
||||
if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) {
|
||||
|
||||
/* insertion-sort it into the maxbuf */
|
||||
for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
|
||||
/* found where it fits */
|
||||
if (toins > jb->hist_maxbuf[j]) {
|
||||
/* move over */
|
||||
memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0]));
|
||||
/* insert */
|
||||
jb->hist_maxbuf[j] = toins;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if the minbuf should get this */
|
||||
if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) {
|
||||
|
||||
/* insertion-sort it into the maxbuf */
|
||||
for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
|
||||
/* found where it fits */
|
||||
if (toins < jb->hist_minbuf[j]) {
|
||||
/* move over */
|
||||
memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0]));
|
||||
/* insert */
|
||||
jb->hist_minbuf[j] = toins;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0) {
|
||||
int k;
|
||||
fprintf(stderr, "toins = %ld\n", toins);
|
||||
fprintf(stderr, "maxbuf =");
|
||||
for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
|
||||
fprintf(stderr, "%ld ", jb->hist_maxbuf[k]);
|
||||
fprintf(stderr, "\nminbuf =");
|
||||
for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
|
||||
fprintf(stderr, "%ld ", jb->hist_minbuf[k]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
jb->hist_maxbuf_valid = 1;
|
||||
}
|
||||
|
||||
static void history_get(jitterbuf *jb)
|
||||
{
|
||||
long max, min, jitter;
|
||||
int index;
|
||||
int count;
|
||||
|
||||
if (!jb->hist_maxbuf_valid)
|
||||
history_calc_maxbuf(jb);
|
||||
|
||||
/* count is how many items in history we're examining */
|
||||
count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ;
|
||||
|
||||
/* index is the "n"ths highest/lowest that we'll look for */
|
||||
index = count * JB_HISTORY_DROPPCT / 100;
|
||||
|
||||
/* sanity checks for index */
|
||||
if (index > (JB_HISTORY_MAXBUF_SZ - 1))
|
||||
index = JB_HISTORY_MAXBUF_SZ - 1;
|
||||
|
||||
|
||||
if (index < 0) {
|
||||
jb->info.min = 0;
|
||||
jb->info.jitter = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
max = jb->hist_maxbuf[index];
|
||||
min = jb->hist_minbuf[index];
|
||||
|
||||
jitter = max - min;
|
||||
|
||||
/* these debug stmts compare the difference between looking at the absolute jitter, and the
|
||||
* values we get by throwing away the outliers */
|
||||
/*
|
||||
fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", index, min, max, jitter);
|
||||
fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", 0, jb->hist_minbuf[0], jb->hist_maxbuf[0], jb->hist_maxbuf[0]-jb->hist_minbuf[0]);
|
||||
*/
|
||||
|
||||
jb->info.min = min;
|
||||
jb->info.jitter = jitter;
|
||||
}
|
||||
|
||||
/* returns 1 if frame was inserted into head of queue, 0 otherwise */
|
||||
static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
|
||||
{
|
||||
jb_frame *frame;
|
||||
jb_frame *p;
|
||||
int head = 0;
|
||||
long resync_ts = ts - jb->info.resync_offset;
|
||||
|
||||
if ((frame = jb->free)) {
|
||||
jb->free = frame->next;
|
||||
} else if (!(frame = (jb_frame *)malloc(sizeof(*frame)))) {
|
||||
jb_err("cannot allocate frame\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
jb->info.frames_cur++;
|
||||
|
||||
frame->data = data;
|
||||
frame->ts = resync_ts;
|
||||
frame->ms = ms;
|
||||
frame->type = type;
|
||||
|
||||
/*
|
||||
* frames are a circular list, jb-frames points to to the lowest ts,
|
||||
* jb->frames->prev points to the highest ts
|
||||
*/
|
||||
|
||||
if (!jb->frames) { /* queue is empty */
|
||||
jb->frames = frame;
|
||||
frame->next = frame;
|
||||
frame->prev = frame;
|
||||
head = 1;
|
||||
} else if (resync_ts < jb->frames->ts) {
|
||||
frame->next = jb->frames;
|
||||
frame->prev = jb->frames->prev;
|
||||
|
||||
frame->next->prev = frame;
|
||||
frame->prev->next = frame;
|
||||
|
||||
/* frame is out of order */
|
||||
jb->info.frames_ooo++;
|
||||
|
||||
jb->frames = frame;
|
||||
head = 1;
|
||||
} else {
|
||||
p = jb->frames;
|
||||
|
||||
/* frame is out of order */
|
||||
if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
|
||||
|
||||
while (resync_ts < p->prev->ts && p->prev != jb->frames)
|
||||
p = p->prev;
|
||||
|
||||
frame->next = p;
|
||||
frame->prev = p->prev;
|
||||
|
||||
frame->next->prev = frame;
|
||||
frame->prev->next = frame;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
static long queue_next(jitterbuf *jb)
|
||||
{
|
||||
if (jb->frames)
|
||||
return jb->frames->ts;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long queue_last(jitterbuf *jb)
|
||||
{
|
||||
if (jb->frames)
|
||||
return jb->frames->prev->ts;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static jb_frame *_queue_get(jitterbuf *jb, long ts, int all)
|
||||
{
|
||||
jb_frame *frame;
|
||||
frame = jb->frames;
|
||||
|
||||
if (!frame)
|
||||
return NULL;
|
||||
|
||||
/*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */
|
||||
|
||||
if (all || ts >= frame->ts) {
|
||||
/* remove this frame */
|
||||
frame->prev->next = frame->next;
|
||||
frame->next->prev = frame->prev;
|
||||
|
||||
if (frame->next == frame)
|
||||
jb->frames = NULL;
|
||||
else
|
||||
jb->frames = frame->next;
|
||||
|
||||
|
||||
/* insert onto "free" single-linked list */
|
||||
frame->next = jb->free;
|
||||
jb->free = frame;
|
||||
|
||||
jb->info.frames_cur--;
|
||||
|
||||
/* we return the frame pointer, even though it's on free list,
|
||||
* but caller must copy data */
|
||||
return frame;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static jb_frame *queue_get(jitterbuf *jb, long ts)
|
||||
{
|
||||
return _queue_get(jb,ts,0);
|
||||
}
|
||||
|
||||
static jb_frame *queue_getall(jitterbuf *jb)
|
||||
{
|
||||
return _queue_get(jb,0,1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* some diagnostics */
|
||||
static void jb_dbginfo(jitterbuf *jb)
|
||||
{
|
||||
if (dbgf == NULL)
|
||||
return;
|
||||
|
||||
jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n",
|
||||
jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur);
|
||||
|
||||
jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n",
|
||||
jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min,
|
||||
jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8);
|
||||
if (jb->info.frames_in > 0)
|
||||
jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n",
|
||||
jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost),
|
||||
jb->info.frames_late * 100/jb->info.frames_in);
|
||||
jb_dbg("jb info: queue %d -> %d. last_ts %d (queue len: %d) last_ms %d\n",
|
||||
queue_next(jb),
|
||||
queue_last(jb),
|
||||
jb->info.next_voice_ts,
|
||||
queue_last(jb) - queue_next(jb),
|
||||
jb->info.last_voice_ms);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEEP_DEBUG
|
||||
static void jb_chkqueue(jitterbuf *jb)
|
||||
{
|
||||
int i=0;
|
||||
jb_frame *p = jb->frames;
|
||||
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (p->next == NULL) {
|
||||
jb_err("Queue is BROKEN at item [%d]", i);
|
||||
}
|
||||
i++;
|
||||
p=p->next;
|
||||
} while (p->next != jb->frames);
|
||||
}
|
||||
|
||||
static void jb_dbgqueue(jitterbuf *jb)
|
||||
{
|
||||
int i=0;
|
||||
jb_frame *p = jb->frames;
|
||||
|
||||
jb_dbg("queue: ");
|
||||
|
||||
if (!p) {
|
||||
jb_dbg("EMPTY\n");
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
jb_dbg("[%d]=%ld ", i++, p->ts);
|
||||
p=p->next;
|
||||
} while (p->next != jb->frames);
|
||||
|
||||
jb_dbg("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now)
|
||||
{
|
||||
jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
|
||||
|
||||
jb->info.frames_in++;
|
||||
|
||||
if (type == JB_TYPE_VOICE) {
|
||||
/* presently, I'm only adding VOICE frames to history and drift
|
||||
* calculations; mostly because with the IAX integrations, I'm
|
||||
* sending retransmitted control frames with their awkward
|
||||
* timestamps through
|
||||
*/
|
||||
if (history_put(jb,ts,now,ms))
|
||||
return JB_DROP;
|
||||
}
|
||||
|
||||
/* if put into head of queue, caller needs to reschedule */
|
||||
if (queue_put(jb,data,type,ms,ts)) {
|
||||
return JB_SCHED;
|
||||
}
|
||||
|
||||
return JB_OK;
|
||||
}
|
||||
|
||||
|
||||
static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
|
||||
{
|
||||
jb_frame *frame;
|
||||
long diff;
|
||||
|
||||
/*if ((now - jb_next(jb)) > 2 * jb->info.last_voice_ms) jb_warn("SCHED: %ld", (now - jb_next(jb))); */
|
||||
/* get jitter info */
|
||||
history_get(jb);
|
||||
|
||||
|
||||
/* target */
|
||||
jb->info.target = jb->info.jitter + jb->info.min + jb->info.conf.target_extra;
|
||||
|
||||
/* if a hard clamp was requested, use it */
|
||||
if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
|
||||
jb_dbg("clamping target from %d to %d\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf);
|
||||
jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf;
|
||||
}
|
||||
|
||||
diff = jb->info.target - jb->info.current;
|
||||
|
||||
/* jb_warn("diff = %d lms=%d last = %d now = %d\n", diff, */
|
||||
/* jb->info.last_voice_ms, jb->info.last_adjustment, now); */
|
||||
|
||||
/* let's work on non-silent case first */
|
||||
if (!jb->info.silence_begin_ts) {
|
||||
/* we want to grow */
|
||||
if ((diff > 0) &&
|
||||
/* we haven't grown in the delay length */
|
||||
(((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) ||
|
||||
/* we need to grow more than the "length" we have left */
|
||||
(diff > queue_last(jb) - queue_next(jb)) ) ) {
|
||||
/* grow by interp frame length */
|
||||
jb->info.current += interpl;
|
||||
jb->info.next_voice_ts += interpl;
|
||||
jb->info.last_voice_ms = interpl;
|
||||
jb->info.last_adjustment = now;
|
||||
jb->info.cnt_contig_interp++;
|
||||
/* assume silence instead of continuing to interpolate */
|
||||
if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
|
||||
jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
|
||||
}
|
||||
jb_dbg("G");
|
||||
return JB_INTERP;
|
||||
}
|
||||
|
||||
frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current);
|
||||
|
||||
/* not a voice frame; just return it. */
|
||||
if (frame && frame->type != JB_TYPE_VOICE) {
|
||||
/* track start of silence */
|
||||
if (frame->type == JB_TYPE_SILENCE) {
|
||||
jb->info.silence_begin_ts = frame->ts;
|
||||
jb->info.cnt_contig_interp = 0;
|
||||
}
|
||||
|
||||
*frameout = *frame;
|
||||
jb->info.frames_out++;
|
||||
jb_dbg("o");
|
||||
return JB_OK;
|
||||
}
|
||||
|
||||
/* voice frame is later than expected */
|
||||
if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
|
||||
if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) {
|
||||
/* either we interpolated past this frame in the last jb_get */
|
||||
/* or the frame is still in order, but came a little too quick */
|
||||
*frameout = *frame;
|
||||
/* reset expectation for next frame */
|
||||
jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
|
||||
jb->info.frames_out++;
|
||||
decrement_losspct(jb);
|
||||
jb->info.cnt_contig_interp = 0;
|
||||
jb_dbg("v");
|
||||
return JB_OK;
|
||||
} else {
|
||||
/* voice frame is late */
|
||||
*frameout = *frame;
|
||||
jb->info.frames_out++;
|
||||
decrement_losspct(jb);
|
||||
jb->info.frames_late++;
|
||||
jb->info.frames_lost--;
|
||||
jb_dbg("l");
|
||||
/*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
|
||||
jb_warninfo(jb); */
|
||||
return JB_DROP;
|
||||
}
|
||||
}
|
||||
|
||||
/* keep track of frame sizes, to allow for variable sized-frames */
|
||||
if (frame && frame->ms > 0) {
|
||||
jb->info.last_voice_ms = frame->ms;
|
||||
}
|
||||
|
||||
/* we want to shrink; shrink at 1 frame / 500ms */
|
||||
/* unless we don't have a frame, then shrink 1 frame */
|
||||
/* every 80ms (though perhaps we can shrink even faster */
|
||||
/* in this case) */
|
||||
if (diff < -jb->info.conf.target_extra &&
|
||||
((!frame && jb->info.last_adjustment + 80 < now) ||
|
||||
(jb->info.last_adjustment + 500 < now))) {
|
||||
|
||||
jb->info.last_adjustment = now;
|
||||
jb->info.cnt_contig_interp = 0;
|
||||
|
||||
if (frame) {
|
||||
*frameout = *frame;
|
||||
/* shrink by frame size we're throwing out */
|
||||
jb->info.current -= frame->ms;
|
||||
jb->info.frames_out++;
|
||||
decrement_losspct(jb);
|
||||
jb->info.frames_dropped++;
|
||||
jb_dbg("s");
|
||||
return JB_DROP;
|
||||
} else {
|
||||
/* shrink by last_voice_ms */
|
||||
jb->info.current -= jb->info.last_voice_ms;
|
||||
jb->info.frames_lost++;
|
||||
increment_losspct(jb);
|
||||
jb_dbg("S");
|
||||
return JB_NOFRAME;
|
||||
}
|
||||
}
|
||||
|
||||
/* lost frame */
|
||||
if (!frame) {
|
||||
/* this is a bit of a hack for now, but if we're close to
|
||||
* target, and we find a missing frame, it makes sense to
|
||||
* grow, because the frame might just be a bit late;
|
||||
* otherwise, we presently get into a pattern where we return
|
||||
* INTERP for the lost frame, then it shows up next, and we
|
||||
* throw it away because it's late */
|
||||
/* I've recently only been able to replicate this using
|
||||
* iaxclient talking to app_echo on asterisk. In this case,
|
||||
* my outgoing packets go through asterisk's (old)
|
||||
* jitterbuffer, and then might get an unusual increasing delay
|
||||
* there if it decides to grow?? */
|
||||
/* Update: that might have been a different bug, that has been fixed..
|
||||
* But, this still seemed like a good idea, except that it ended up making a single actual
|
||||
* lost frame get interpolated two or more times, when there was "room" to grow, so it might
|
||||
* be a bit of a bad idea overall */
|
||||
/*if (diff > -1 * jb->info.last_voice_ms) {
|
||||
jb->info.current += jb->info.last_voice_ms;
|
||||
jb->info.last_adjustment = now;
|
||||
jb_warn("g");
|
||||
return JB_INTERP;
|
||||
} */
|
||||
jb->info.frames_lost++;
|
||||
increment_losspct(jb);
|
||||
jb->info.next_voice_ts += interpl;
|
||||
jb->info.last_voice_ms = interpl;
|
||||
jb->info.cnt_contig_interp++;
|
||||
/* assume silence instead of continuing to interpolate */
|
||||
if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
|
||||
jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
|
||||
}
|
||||
jb_dbg("L");
|
||||
return JB_INTERP;
|
||||
}
|
||||
|
||||
/* normal case; return the frame, increment stuff */
|
||||
*frameout = *frame;
|
||||
jb->info.next_voice_ts += frame->ms;
|
||||
jb->info.frames_out++;
|
||||
jb->info.cnt_contig_interp = 0;
|
||||
decrement_losspct(jb);
|
||||
jb_dbg("v");
|
||||
return JB_OK;
|
||||
} else {
|
||||
/* TODO: after we get the non-silent case down, we'll make the
|
||||
* silent case -- basically, we'll just grow and shrink faster
|
||||
* here, plus handle next_voice_ts a bit differently */
|
||||
|
||||
/* to disable silent special case altogether, just uncomment this: */
|
||||
/* jb->info.silence_begin_ts = 0; */
|
||||
|
||||
/* shrink interpl len every 10ms during silence */
|
||||
if (diff < -jb->info.conf.target_extra &&
|
||||
jb->info.last_adjustment + 10 <= now) {
|
||||
jb->info.current -= interpl;
|
||||
jb->info.last_adjustment = now;
|
||||
}
|
||||
|
||||
frame = queue_get(jb, now - jb->info.current);
|
||||
if (!frame) {
|
||||
return JB_NOFRAME;
|
||||
} else if (frame->type != JB_TYPE_VOICE) {
|
||||
/* normal case; in silent mode, got a non-voice frame */
|
||||
*frameout = *frame;
|
||||
jb->info.frames_out++;
|
||||
return JB_OK;
|
||||
}
|
||||
if (frame->ts < jb->info.silence_begin_ts) {
|
||||
/* voice frame is late */
|
||||
*frameout = *frame;
|
||||
jb->info.frames_out++;
|
||||
decrement_losspct(jb);
|
||||
jb->info.frames_late++;
|
||||
jb->info.frames_lost--;
|
||||
jb_dbg("l");
|
||||
/*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
|
||||
jb_warninfo(jb); */
|
||||
return JB_DROP;
|
||||
} else {
|
||||
/* voice frame */
|
||||
/* try setting current to target right away here */
|
||||
jb->info.current = jb->info.target;
|
||||
jb->info.silence_begin_ts = 0;
|
||||
jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
|
||||
jb->info.last_voice_ms = frame->ms;
|
||||
jb->info.frames_out++;
|
||||
decrement_losspct(jb);
|
||||
*frameout = *frame;
|
||||
jb_dbg("V");
|
||||
return JB_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long jb_next(jitterbuf *jb)
|
||||
{
|
||||
if (jb->info.silence_begin_ts) {
|
||||
if (jb->frames) {
|
||||
long next = queue_next(jb);
|
||||
history_get(jb);
|
||||
/* shrink during silence */
|
||||
if (jb->info.target - jb->info.current < -jb->info.conf.target_extra)
|
||||
return jb->info.last_adjustment + 10;
|
||||
return next + jb->info.target;
|
||||
}
|
||||
else
|
||||
return JB_LONGMAX;
|
||||
} else {
|
||||
return jb->info.next_voice_ts;
|
||||
}
|
||||
}
|
||||
|
||||
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
|
||||
{
|
||||
enum jb_return_code ret = _jb_get(jb, frameout, now, interpl);
|
||||
#if 0
|
||||
static int lastts=0;
|
||||
int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0;
|
||||
jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists);
|
||||
if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
|
||||
lastts = thists;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
|
||||
{
|
||||
jb_frame *frame;
|
||||
frame = queue_getall(jb);
|
||||
|
||||
if (!frame) {
|
||||
return JB_NOFRAME;
|
||||
}
|
||||
|
||||
*frameout = *frame;
|
||||
return JB_OK;
|
||||
}
|
||||
|
||||
|
||||
enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)
|
||||
{
|
||||
history_get(jb);
|
||||
|
||||
*stats = jb->info;
|
||||
|
||||
return JB_OK;
|
||||
}
|
||||
|
||||
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
|
||||
{
|
||||
/* take selected settings from the struct */
|
||||
|
||||
jb->info.conf.max_jitterbuf = conf->max_jitterbuf;
|
||||
jb->info.conf.resync_threshold = conf->resync_threshold;
|
||||
jb->info.conf.max_contig_interp = conf->max_contig_interp;
|
||||
|
||||
/* -1 indicates use of the default JB_TARGET_EXTRA value */
|
||||
jb->info.conf.target_extra = ( conf->target_extra == -1 )
|
||||
? JB_TARGET_EXTRA
|
||||
: conf->target_extra
|
||||
;
|
||||
|
||||
/* update these to match new target_extra setting */
|
||||
jb->info.current = jb->info.conf.target_extra;
|
||||
jb->info.target = jb->info.conf.target_extra;
|
||||
|
||||
return JB_OK;
|
||||
}
|
||||
|
||||
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* jitterbuf: an application-independent jitterbuffer
|
||||
*
|
||||
* Copyrights:
|
||||
* Copyright (C) 2004-2005, Horizon Wimba, Inc.
|
||||
*
|
||||
* Contributors:
|
||||
* Steve Kann <stevek@stevek.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU Lesser (Library) General Public License
|
||||
*
|
||||
* Copyright on this file is disclaimed to Digium for inclusion in Asterisk
|
||||
*/
|
||||
|
||||
#ifndef _JITTERBUF_H_
|
||||
#define _JITTERBUF_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* configuration constants */
|
||||
/* Number of historical timestamps to use in calculating jitter and drift */
|
||||
#define JB_HISTORY_SZ 500
|
||||
/* what percentage of timestamps should we drop from the history when we examine it;
|
||||
* this might eventually be something made configurable */
|
||||
#define JB_HISTORY_DROPPCT 3
|
||||
/* the maximum droppct we can handle (say it was configurable). */
|
||||
#define JB_HISTORY_DROPPCT_MAX 4
|
||||
/* the size of the buffer we use to keep the top and botton timestamps for dropping */
|
||||
#define JB_HISTORY_MAXBUF_SZ JB_HISTORY_SZ * JB_HISTORY_DROPPCT_MAX / 100
|
||||
/* amount of additional jitterbuffer adjustment */
|
||||
#define JB_TARGET_EXTRA 40
|
||||
/* ms between growing and shrinking; may not be honored if jitterbuffer runs out of space */
|
||||
#define JB_ADJUST_DELAY 40
|
||||
|
||||
enum jb_return_code {
|
||||
/* return codes */
|
||||
JB_OK, /* 0 */
|
||||
JB_EMPTY, /* 1 */
|
||||
JB_NOFRAME, /* 2 */
|
||||
JB_INTERP, /* 3 */
|
||||
JB_DROP, /* 4 */
|
||||
JB_SCHED /* 5 */
|
||||
};
|
||||
|
||||
enum jb_frame_type {
|
||||
/* frame types */
|
||||
JB_TYPE_CONTROL, /* 0 */
|
||||
JB_TYPE_VOICE, /* 1 */
|
||||
JB_TYPE_VIDEO, /* 2 - reserved */
|
||||
JB_TYPE_SILENCE /* 3 */
|
||||
};
|
||||
|
||||
typedef struct jb_conf {
|
||||
/* settings */
|
||||
long max_jitterbuf; /* defines a hard clamp to use in setting the jitter buffer delay */
|
||||
long resync_threshold; /* the jb will resync when delay increases to (2 * jitter) + this param */
|
||||
long max_contig_interp; /* the max interp frames to return in a row */
|
||||
long target_extra; /* amount of additional jitterbuffer adjustment, overrides JB_TARGET_EXTRA */
|
||||
} jb_conf;
|
||||
|
||||
typedef struct jb_info {
|
||||
jb_conf conf;
|
||||
|
||||
/* statistics */
|
||||
long frames_in; /* number of frames input to the jitterbuffer.*/
|
||||
long frames_out; /* number of frames output from the jitterbuffer.*/
|
||||
long frames_late; /* number of frames which were too late, and dropped.*/
|
||||
long frames_lost; /* number of missing frames.*/
|
||||
long frames_dropped; /* number of frames dropped (shrinkage) */
|
||||
long frames_ooo; /* number of frames received out-of-order */
|
||||
long frames_cur; /* number of frames presently in jb, awaiting delivery.*/
|
||||
long jitter; /* jitter measured within current history interval*/
|
||||
long min; /* minimum lateness within current history interval */
|
||||
long current; /* the present jitterbuffer adjustment */
|
||||
long target; /* the target jitterbuffer adjustment */
|
||||
long losspct; /* recent lost frame percentage (* 1000) */
|
||||
long next_voice_ts; /* the ts of the next frame to be read from the jb - in receiver's time */
|
||||
long last_voice_ms; /* the duration of the last voice frame */
|
||||
long silence_begin_ts; /* the time of the last CNG frame, when in silence */
|
||||
long last_adjustment; /* the time of the last adjustment */
|
||||
long last_delay; /* the last now added to history */
|
||||
long cnt_delay_discont; /* the count of discontinuous delays */
|
||||
long resync_offset; /* the amount to offset ts to support resyncs */
|
||||
long cnt_contig_interp; /* the number of contiguous interp frames returned */
|
||||
} jb_info;
|
||||
|
||||
typedef struct jb_frame {
|
||||
void *data; /* the frame data */
|
||||
long ts; /* the relative delivery time expected */
|
||||
long ms; /* the time covered by this frame, in sec/8000 */
|
||||
enum jb_frame_type type; /* the type of frame */
|
||||
struct jb_frame *next, *prev;
|
||||
} jb_frame;
|
||||
|
||||
typedef struct jitterbuf {
|
||||
jb_info info;
|
||||
|
||||
/* history */
|
||||
long history[JB_HISTORY_SZ]; /* history */
|
||||
int hist_ptr; /* points to index in history for next entry */
|
||||
long hist_maxbuf[JB_HISTORY_MAXBUF_SZ]; /* a sorted buffer of the max delays (highest first) */
|
||||
long hist_minbuf[JB_HISTORY_MAXBUF_SZ]; /* a sorted buffer of the min delays (lowest first) */
|
||||
int hist_maxbuf_valid; /* are the "maxbuf"/minbuf valid? */
|
||||
|
||||
jb_frame *frames; /* queued frames */
|
||||
jb_frame *free; /* free frames (avoid malloc?) */
|
||||
} jitterbuf;
|
||||
|
||||
|
||||
/* new jitterbuf */
|
||||
jitterbuf * jb_new(void);
|
||||
|
||||
/* destroy jitterbuf */
|
||||
void jb_destroy(jitterbuf *jb);
|
||||
|
||||
/* reset jitterbuf */
|
||||
/* NOTE: The jitterbuffer should be empty before you call this, otherwise
|
||||
* you will leak queued frames, and some internal structures */
|
||||
void jb_reset(jitterbuf *jb);
|
||||
|
||||
/* queue a frame data=frame data, timings (in ms): ms=length of frame (for voice), ts=ts (sender's time)
|
||||
* now=now (in receiver's time) return value is one of
|
||||
* JB_OK: Frame added. Last call to jb_next() still valid
|
||||
* JB_DROP: Drop this frame immediately
|
||||
* JB_SCHED: Frame added. Call jb_next() to get a new time for the next frame
|
||||
*/
|
||||
enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now);
|
||||
|
||||
/* get a frame for time now (receiver's time) return value is one of
|
||||
* JB_OK: You've got frame!
|
||||
* JB_DROP: Here's an audio frame you should just drop. Ask me again for this time..
|
||||
* JB_NOFRAME: There's no frame scheduled for this time.
|
||||
* JB_INTERP: Please interpolate an interpl-length frame for this time (either we need to grow, or there was a lost frame)
|
||||
* JB_EMPTY: The jb is empty.
|
||||
*/
|
||||
enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frame, long now, long interpl);
|
||||
|
||||
/* unconditionally get frames from jitterbuf until empty */
|
||||
enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout);
|
||||
|
||||
/* when is the next frame due out, in receiver's time (0=EMPTY)
|
||||
* This value may change as frames are added (esp non-audio frames) */
|
||||
long jb_next(jitterbuf *jb);
|
||||
|
||||
/* get jitterbuf info: only "statistics" may be valid */
|
||||
enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats);
|
||||
|
||||
/* set jitterbuf conf */
|
||||
enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf);
|
||||
|
||||
typedef void (*jb_output_function_t)(const char *fmt, ...);
|
||||
extern void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
/* MD5 checksum routines used for authentication. Not covered by GPL, but
|
||||
in the public domain as per the copyright below */
|
||||
|
||||
#ifdef FREEBSD
|
||||
# include <machine/endian.h>
|
||||
#elif defined(LINUX)
|
||||
# include <endian.h>
|
||||
# include <features.h>
|
||||
# include <sys/types.h>
|
||||
#elif defined(SOLARIS)
|
||||
/* each solaris is different -- this won't work on 2.6 or 2.7 */
|
||||
# include <sys/isa_defs.h> /* Defines either _LITTLE_ENDIAN or _BIG_ENDIAN */
|
||||
# define __BIG_ENDIAN 4321
|
||||
# define __LITTLE_ENDIAN 1234
|
||||
# define BIG_ENDIAN 4321
|
||||
# define LITTLE_ENDIAN 1234
|
||||
# ifdef _LITTLE_ENDIAN
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
# define BYTE_ORDER LITTLE_ENDIAN
|
||||
# else
|
||||
# define __BYTE_ORDER __BIG_ENDIAN
|
||||
# define BYTE_ORDER BIG_ENDIAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN || BYTE_ORDER == BIG_ENDIAN
|
||||
# define HIGHFIRST 1
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN || BYTE_ORDER == LITLE_ENDIAN
|
||||
# undef HIGHFIRST
|
||||
#else
|
||||
# error "Please fix <bits/endian.h>"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
#include <string.h> /* for memcpy() */
|
||||
#include "md5.h"
|
||||
|
||||
#ifndef HIGHFIRST
|
||||
#define byteReverse(buf, len) /* Nothing */
|
||||
#else
|
||||
void byteReverse(uint8_t *buf, unsigned int longs);
|
||||
|
||||
#ifndef ASM_MD5
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
void byteReverse(uint8_t *buf, unsigned int longs)
|
||||
{
|
||||
uint32_t t;
|
||||
do {
|
||||
t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(uint32_t *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MD5Init(struct MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MD5Update(struct MD5Context *ctx, uint8_t const *buf, unsigned int len)
|
||||
{
|
||||
uint32_t t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
uint8_t *p = (uint8_t *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memcpy(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memcpy(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
memcpy(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Final(uint8_t digest[16], struct MD5Context *ctx)
|
||||
{
|
||||
unsigned int count;
|
||||
uint8_t *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((uint32_t *) ctx->in)[14] = ctx->bits[0];
|
||||
((uint32_t *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
byteReverse((uint8_t *) ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
#ifndef ASM_MD5
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void MD5Transform(uint32_t buf[4], uint32_t const in[16])
|
||||
{
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#endif
|
||||
|
||||
struct MD5Context {
|
||||
uint32_t buf[4];
|
||||
uint32_t bits[2];
|
||||
uint8_t in[64];
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *context);
|
||||
void MD5Update(struct MD5Context *context, uint8_t const *buf, unsigned int len);
|
||||
void MD5Final(uint8_t digest[16], struct MD5Context *context);
|
||||
void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
|
||||
|
||||
/*
|
||||
* This is needed to make RSAREF happy on some MS-DOS compilers.
|
||||
*/
|
||||
typedef struct MD5Context MD5_CTX;
|
||||
|
||||
#endif /* !MD5_H */
|
||||
+776
@@ -0,0 +1,776 @@
|
||||
/*
|
||||
* Miniphone: A simple, command line telephone
|
||||
*
|
||||
* IAX Support for talking to Asterisk and other Gnophone clients
|
||||
*
|
||||
* Copyright (C) 1999, Linux Support Services, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <iax-client.h>
|
||||
#include <linux/soundcard.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <gsm.h>
|
||||
#include <miniphone.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "busy.h"
|
||||
#include "dialtone.h"
|
||||
#include "answer.h"
|
||||
#include "ringtone.h"
|
||||
#include "ring10.h"
|
||||
#include "options.h"
|
||||
|
||||
#define FRAME_SIZE 160
|
||||
|
||||
static char callerid[80];
|
||||
|
||||
struct peer {
|
||||
int time;
|
||||
gsm gsmin;
|
||||
gsm gsmout;
|
||||
|
||||
struct iax_session *session;
|
||||
struct peer *next;
|
||||
};
|
||||
|
||||
static char *audiodev = "/dev/dsp";
|
||||
static int audiofd = -1;
|
||||
static struct peer *peers;
|
||||
static int answered_call = 0;
|
||||
|
||||
static struct peer *find_peer(struct iax_session *);
|
||||
static int audio_setup(char *);
|
||||
static void sighandler(int);
|
||||
static void parse_args(FILE *, unsigned char *);
|
||||
void do_iax_event(FILE *);
|
||||
void call(FILE *, char *);
|
||||
void answer_call(void);
|
||||
void reject_call(void);
|
||||
static void handle_event(FILE *, struct iax_event *e, struct peer *p);
|
||||
void parse_cmd(FILE *, int, char **);
|
||||
void issue_prompt(FILE *);
|
||||
void dump_array(FILE *, char **);
|
||||
|
||||
struct sound {
|
||||
short *data;
|
||||
int datalen;
|
||||
int samplen;
|
||||
int silencelen;
|
||||
int repeat;
|
||||
};
|
||||
|
||||
static int cursound = -1;
|
||||
|
||||
static int sampsent = 0;
|
||||
static int offset = 0;
|
||||
static int silencelen = 0;
|
||||
static int nosound = 0;
|
||||
|
||||
static int offhook = 0;
|
||||
static int ringing = 0;
|
||||
|
||||
static int writeonly = 0;
|
||||
|
||||
static struct iax_session *registry = NULL;
|
||||
static struct timeval regtime;
|
||||
|
||||
#define TONE_NONE -1
|
||||
#define TONE_RINGTONE 0
|
||||
#define TONE_BUSY 1
|
||||
#define TONE_CONGEST 2
|
||||
#define TONE_RINGER 3
|
||||
#define TONE_ANSWER 4
|
||||
#define TONE_DIALTONE 5
|
||||
|
||||
#define OUTPUT_NONE 0
|
||||
#define OUTPUT_SPEAKER 1
|
||||
#define OUTPUT_HANDSET 2
|
||||
#define OUTPUT_BOTH 3
|
||||
|
||||
static struct sound sounds[] = {
|
||||
{ ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
|
||||
{ busy, sizeof(busy)/2, 4000, 4000, 1 },
|
||||
{ busy, sizeof(busy)/2, 2000, 2000, 1 },
|
||||
{ ring10, sizeof(ring10)/2, 16000, 32000, 1 },
|
||||
{ answer, sizeof(answer)/2, 2200, 0, 0 },
|
||||
{ dialtone, sizeof(dialtone)/2, 8000, 0, 1 },
|
||||
};
|
||||
|
||||
static char *help[] = {
|
||||
"Welcome to the miniphone telephony client, the commands are as follows:\n",
|
||||
"Help\t\t-\tDisplays this screen.",
|
||||
"Help <Command>\t-\tInqueries specific information on a command.",
|
||||
"Dial <Number>\t-\tDials the number supplied in the first arguement",
|
||||
"Status\t\t-\tLists the current sessions and their current status.",
|
||||
"Quit\t\t-\tShuts down the client.",
|
||||
"",
|
||||
0
|
||||
};
|
||||
|
||||
static short silence[FRAME_SIZE];
|
||||
|
||||
static struct peer *most_recent_answer;
|
||||
static struct iax_session *newcall = 0;
|
||||
|
||||
static struct peer *find_peer(struct iax_session *session)
|
||||
{
|
||||
struct peer *cur = peers;
|
||||
while(cur) {
|
||||
if (cur->session == session)
|
||||
return cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int audio_setup(char *dev)
|
||||
{
|
||||
int fd;
|
||||
int fmt = AFMT_S16_LE;
|
||||
int channels = 1;
|
||||
int speed = 8000;
|
||||
int fragsize = (40 << 16) | 6;
|
||||
if ( (fd = open(dev, O_RDWR | O_NONBLOCK)) < 0) {
|
||||
fprintf(stderr, "Unable to open audio device %s: %s\n", dev, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) || (fmt != AFMT_S16_LE)) {
|
||||
fprintf(stderr, "Unable to set in signed linear format.\n");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0)) {
|
||||
fprintf(stderr, "Unable to set full duplex operation.\n");
|
||||
writeonly = 1;
|
||||
/* return -1; */
|
||||
}
|
||||
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) || (channels != 1)) {
|
||||
fprintf(stderr, "Unable to set to mono\n");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) || (speed != 8000)) {
|
||||
fprintf(stderr, "Unable to set speed to 8000 hz\n");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragsize)) {
|
||||
fprintf(stderr, "Unable to set fragment size...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int send_sound(int soundfd)
|
||||
{
|
||||
/* Send FRAME_SIZE samples of whatever */
|
||||
short myframe[FRAME_SIZE];
|
||||
short *frame = NULL;
|
||||
int total = FRAME_SIZE;
|
||||
int amt=0;
|
||||
int res;
|
||||
int myoff;
|
||||
audio_buf_info abi;
|
||||
if (cursound > -1) {
|
||||
res = ioctl(soundfd, SNDCTL_DSP_GETOSPACE ,&abi);
|
||||
if (res) {
|
||||
fprintf(stderr,"Unable to read output space\n");
|
||||
return -1;
|
||||
}
|
||||
/* Calculate how many samples we can send, max */
|
||||
if (total > (abi.fragments * abi.fragsize / 2))
|
||||
total = abi.fragments * abi.fragsize / 2;
|
||||
res = total;
|
||||
if (sampsent < sounds[cursound].samplen) {
|
||||
myoff=0;
|
||||
while(total) {
|
||||
amt = total;
|
||||
if (amt > (sounds[cursound].datalen - offset))
|
||||
amt = sounds[cursound].datalen - offset;
|
||||
memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2);
|
||||
total -= amt;
|
||||
offset += amt;
|
||||
sampsent += amt;
|
||||
myoff += amt;
|
||||
if (offset >= sounds[cursound].datalen)
|
||||
offset = 0;
|
||||
}
|
||||
/* Set it up for silence */
|
||||
if (sampsent >= sounds[cursound].samplen)
|
||||
silencelen = sounds[cursound].silencelen;
|
||||
frame = myframe;
|
||||
} else {
|
||||
if (silencelen > 0) {
|
||||
frame = silence;
|
||||
silencelen -= res;
|
||||
} else {
|
||||
if (sounds[cursound].repeat) {
|
||||
/* Start over */
|
||||
sampsent = 0;
|
||||
offset = 0;
|
||||
} else {
|
||||
cursound = -1;
|
||||
nosound = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if (frame)
|
||||
printf("res is %d, frame[0] is %d\n", res, frame[0]);
|
||||
#endif
|
||||
res = write(soundfd, frame, res * 2);
|
||||
if (res > 0)
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iax_regtimeout(int timeout)
|
||||
{
|
||||
if (timeout) {
|
||||
gettimeofday(®time, NULL);
|
||||
regtime.tv_sec += timeout;
|
||||
} else {
|
||||
regtime.tv_usec = 0;
|
||||
regtime.tv_sec = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_iax_register(void)
|
||||
{
|
||||
int res;
|
||||
if (strlen(regpeer) && strlen(server)) {
|
||||
registry = iax_session_new();
|
||||
|
||||
res = iax_register(registry, server,regpeer,regsecret, refresh);
|
||||
|
||||
if (res) {
|
||||
fprintf(stderr, "Failed registration: %s\n", iax_errstr);
|
||||
return -1;
|
||||
}
|
||||
iax_regtimeout(5 * refresh / 6);
|
||||
} else {
|
||||
iax_regtimeout(0);
|
||||
refresh = 60;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_iax_timeout(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
int ms;
|
||||
if (!regtime.tv_usec || !regtime.tv_sec)
|
||||
return -1;
|
||||
gettimeofday(&tv, NULL);
|
||||
if ((tv.tv_usec >= regtime.tv_usec) && (tv.tv_sec >= regtime.tv_sec)) {
|
||||
check_iax_register();
|
||||
/* Have it check again soon */
|
||||
return 100;
|
||||
}
|
||||
ms = (regtime.tv_sec - tv.tv_sec) * 1000 + (regtime.tv_usec - tv.tv_usec) / 1000;
|
||||
return ms;
|
||||
}
|
||||
|
||||
static int gentone(int sound, int uninterruptible)
|
||||
{
|
||||
cursound = sound;
|
||||
sampsent = 0;
|
||||
offset = 0;
|
||||
silencelen = 0;
|
||||
nosound = uninterruptible;
|
||||
printf("Sending tone %d\n", sound);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
sighandler(int sig)
|
||||
{
|
||||
if(sig == SIGHUP) {
|
||||
puts("rehashing!");
|
||||
} else if(sig == SIGINT) {
|
||||
static int prev = 0;
|
||||
int cur;
|
||||
|
||||
if ( (cur = time(0))-prev <= 5) {
|
||||
printf("Terminating!\n");
|
||||
exit(0);
|
||||
} else {
|
||||
prev = cur;
|
||||
printf("Press interrupt key again in the next %d seconds to really terminate\n", 5-(cur-prev));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse_args(FILE *f, unsigned char *cmd)
|
||||
{
|
||||
static char *argv[MAXARGS];
|
||||
unsigned char *parse = cmd;
|
||||
int argc = 0, t = 0;
|
||||
|
||||
// Don't mess with anything that doesn't exist...
|
||||
if(!*parse)
|
||||
return;
|
||||
|
||||
bzero(argv, sizeof(argv));
|
||||
while(*parse) {
|
||||
if(*parse < 33 || *parse > 128) {
|
||||
*parse = 0, t++;
|
||||
if(t > MAXARG) {
|
||||
fprintf(f, "Warning: Argument exceeds maximum argument size, command ignored!\n");
|
||||
return;
|
||||
}
|
||||
} else if(t || !argc) {
|
||||
if(argc == MAXARGS) {
|
||||
fprintf(f, "Warning: Command ignored, too many arguments\n");
|
||||
return;
|
||||
}
|
||||
argv[argc++] = parse;
|
||||
t = 0;
|
||||
}
|
||||
|
||||
parse++;
|
||||
}
|
||||
|
||||
if(argc)
|
||||
parse_cmd(f, argc, argv);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int port;
|
||||
int netfd;
|
||||
int c, h=0, m, regm;
|
||||
FILE *f;
|
||||
int fd = STDIN_FILENO;
|
||||
char rcmd[RBUFSIZE];
|
||||
fd_set readfd;
|
||||
fd_set writefd;
|
||||
struct timeval timer;
|
||||
struct timeval *timerptr = NULL;
|
||||
gsm_frame fo;
|
||||
|
||||
load_options();
|
||||
|
||||
if (!strlen(callerid))
|
||||
gethostname(callerid, sizeof(callerid));
|
||||
|
||||
signal(SIGHUP, sighandler);
|
||||
signal(SIGINT, sighandler);
|
||||
|
||||
if ( !(f = fdopen(fd, "w+"))) {
|
||||
fprintf(stderr, "Unable to create file on fd %d\n", fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( (audiofd = audio_setup(audiodev)) == -1) {
|
||||
fprintf(stderr, "Fatal error: failed to open sound device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( (port = iax_init(0) < 0)) {
|
||||
fprintf(stderr, "Fatal error: failed to initialize iax with port %d\n", port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iax_set_formats(AST_FORMAT_GSM);
|
||||
netfd = iax_get_fd();
|
||||
|
||||
check_iax_register();
|
||||
|
||||
fprintf(f, "Text Based Telephony Client.\n\n");
|
||||
issue_prompt(f);
|
||||
|
||||
timer.tv_sec = 0;
|
||||
timer.tv_usec = 0;
|
||||
|
||||
while(1) {
|
||||
FD_ZERO(&readfd);
|
||||
FD_ZERO(&writefd);
|
||||
FD_SET(fd, &readfd);
|
||||
if(fd > h)
|
||||
h = fd;
|
||||
if(answered_call && !writeonly) {
|
||||
FD_SET(audiofd, &readfd);
|
||||
if(audiofd > h)
|
||||
h = audiofd;
|
||||
}
|
||||
if (cursound > -1) {
|
||||
FD_SET(audiofd, &writefd);
|
||||
if (audiofd > h)
|
||||
h = audiofd;
|
||||
}
|
||||
FD_SET(netfd, &readfd);
|
||||
if(netfd > h)
|
||||
h = netfd;
|
||||
|
||||
if ( (c = select(h+1, &readfd, &writefd, 0, timerptr)) >= 0) {
|
||||
if(FD_ISSET(fd, &readfd)) {
|
||||
if ( ( fgets(&*rcmd, 256, f))) {
|
||||
rcmd[strlen(rcmd)-1] = 0;
|
||||
parse_args(f, &*rcmd);
|
||||
} else fprintf(f, "Fatal error: failed to read data!\n");
|
||||
|
||||
issue_prompt(f);
|
||||
}
|
||||
if(answered_call) {
|
||||
if(FD_ISSET(audiofd, &readfd)) {
|
||||
static int ret, rlen = 0;
|
||||
static short rbuf[FRAME_SIZE];
|
||||
|
||||
if ( (ret = read(audiofd, rbuf + rlen, 2 * (FRAME_SIZE-rlen))) == -1) {
|
||||
puts("Failed to read audio.");
|
||||
return -1;
|
||||
}
|
||||
rlen += ret/2;
|
||||
if(rlen == FRAME_SIZE) {
|
||||
rlen = 0;
|
||||
|
||||
if(!most_recent_answer->gsmout)
|
||||
most_recent_answer->gsmout = gsm_create();
|
||||
|
||||
gsm_encode(most_recent_answer->gsmout, rbuf, fo);
|
||||
if(iax_send_voice(most_recent_answer->session,
|
||||
AST_FORMAT_GSM, (char *)fo, sizeof(fo)) == -1)
|
||||
puts("Failed to send voice!");
|
||||
}
|
||||
}
|
||||
}
|
||||
do_iax_event(f);
|
||||
m = iax_time_to_next_event();
|
||||
if(m > -1) {
|
||||
timerptr = &timer;
|
||||
timer.tv_sec = m /1000;
|
||||
timer.tv_usec = (m % 1000) * 1000;
|
||||
} else
|
||||
timerptr = 0;
|
||||
regm = check_iax_timeout();
|
||||
if (!timerptr || (m > regm)) {
|
||||
timerptr = &timer;
|
||||
timer.tv_sec = regm /1000;
|
||||
timer.tv_usec = (regm % 1000) * 1000;
|
||||
}
|
||||
if (FD_ISSET(audiofd, &writefd)) {
|
||||
send_sound(audiofd);
|
||||
}
|
||||
} else {
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
fprintf(stderr, "Fatal error in select(): %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
do_iax_event(FILE *f) {
|
||||
int sessions = 0;
|
||||
struct iax_event *e = 0;
|
||||
struct peer *peer;
|
||||
|
||||
while ( (e = iax_get_event(0))) {
|
||||
peer = find_peer(e->session);
|
||||
if(peer) {
|
||||
handle_event(f, e, peer);
|
||||
} else if (e->session == registry) {
|
||||
fprintf(stderr, "Registration complete: %s (%d)\n",
|
||||
(e->event.regreply.status == IAX_REG_SUCCESS) ? "Success" : "Failed",
|
||||
e->event.regreply.status);
|
||||
registry = NULL;
|
||||
} else {
|
||||
if(e->etype != IAX_EVENT_CONNECT) {
|
||||
fprintf(stderr, "Huh? This is an event for a non-existant session?\n");
|
||||
continue;
|
||||
}
|
||||
sessions++;
|
||||
|
||||
if(sessions >= MAX_SESSIONS) {
|
||||
fprintf(f, "Missed a call... too many sessions open.\n");
|
||||
}
|
||||
|
||||
|
||||
if(e->event.connect.callerid && e->event.connect.dnid)
|
||||
fprintf(f, "Call from '%s' for '%s'", e->event.connect.callerid,
|
||||
e->event.connect.dnid);
|
||||
else if(e->event.connect.dnid) {
|
||||
fprintf(f, "Call from '%s'", e->event.connect.dnid);
|
||||
} else if(e->event.connect.callerid) {
|
||||
fprintf(f, "Call from '%s'", e->event.connect.callerid);
|
||||
} else printf("Call from");
|
||||
fprintf(f, " (%s)\n", inet_ntoa(iax_get_peer_addr(e->session).sin_addr));
|
||||
|
||||
if(most_recent_answer) {
|
||||
fprintf(f, "Incoming call ignored, there's already a call waiting for answer... \
|
||||
please accept or reject first\n");
|
||||
iax_reject(e->session, "Too many calls, we're busy!");
|
||||
} else {
|
||||
if ( !(peer = malloc(sizeof(struct peer)))) {
|
||||
fprintf(f, "Warning: Unable to allocate memory!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
peer->time = time(0);
|
||||
peer->session = e->session;
|
||||
if (peer->gsmin)
|
||||
free(peer->gsmin);
|
||||
peer->gsmin = 0;
|
||||
if (peer->gsmout)
|
||||
free(peer->gsmout);
|
||||
peer->gsmout = 0;
|
||||
|
||||
peer->next = peers;
|
||||
peers = peer;
|
||||
|
||||
iax_accept(peer->session);
|
||||
iax_ring_announce(peer->session);
|
||||
most_recent_answer = peer;
|
||||
ringing = 1;
|
||||
gentone(TONE_RINGER, 0);
|
||||
fprintf(f, "Incoming call!\n");
|
||||
}
|
||||
issue_prompt(f);
|
||||
}
|
||||
iax_event_free(e);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
call(FILE *f, char *num)
|
||||
{
|
||||
struct peer *peer;
|
||||
|
||||
if(!newcall)
|
||||
newcall = iax_session_new();
|
||||
else {
|
||||
fprintf(f, "Already attempting to call somewhere, please cancel first!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !(peer = malloc(sizeof(struct peer)))) {
|
||||
fprintf(f, "Warning: Unable to allocate memory!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
peer->time = time(0);
|
||||
peer->session = newcall;
|
||||
peer->gsmin = 0;
|
||||
peer->gsmout = 0;
|
||||
|
||||
peer->next = peers;
|
||||
peers = peer;
|
||||
|
||||
most_recent_answer = peer;
|
||||
|
||||
offhook = 1;
|
||||
|
||||
iax_call(peer->session, callerid, num, NULL, 10);
|
||||
}
|
||||
|
||||
void
|
||||
answer_call(void)
|
||||
{
|
||||
if(most_recent_answer)
|
||||
iax_answer(most_recent_answer->session);
|
||||
printf("Answering call!\n");
|
||||
answered_call = 1;
|
||||
offhook = 1;
|
||||
ringing = 0;
|
||||
gentone(TONE_ANSWER, 1);
|
||||
}
|
||||
|
||||
void
|
||||
reject_call(void)
|
||||
{
|
||||
iax_reject(most_recent_answer->session, "Call rejected manually.");
|
||||
most_recent_answer = 0;
|
||||
ringing = 0;
|
||||
gentone(TONE_NONE, 1);
|
||||
}
|
||||
|
||||
void
|
||||
handle_event(FILE *f, struct iax_event *e, struct peer *p)
|
||||
{
|
||||
short fr[FRAME_SIZE];
|
||||
int len;
|
||||
|
||||
switch(e->etype) {
|
||||
case IAX_EVENT_HANGUP:
|
||||
iax_hangup(most_recent_answer->session, "Byeee!");
|
||||
fprintf(f, "Call disconnected by peer\n");
|
||||
free(most_recent_answer);
|
||||
most_recent_answer = 0;
|
||||
answered_call = 0;
|
||||
peers = 0;
|
||||
newcall = 0;
|
||||
if (offhook)
|
||||
gentone(TONE_CONGEST, 0);
|
||||
break;
|
||||
|
||||
case IAX_EVENT_REJECT:
|
||||
fprintf(f, "Authentication was rejected\n");
|
||||
break;
|
||||
case IAX_EVENT_ACCEPT:
|
||||
fprintf(f, "Accepted...\n");
|
||||
issue_prompt(f);
|
||||
break;
|
||||
case IAX_EVENT_RINGA:
|
||||
fprintf(f, "Ringing...\n");
|
||||
issue_prompt(f);
|
||||
gentone(TONE_RINGTONE, 0);
|
||||
break;
|
||||
case IAX_EVENT_ANSWER:
|
||||
answer_call();
|
||||
gentone(TONE_ANSWER, 1);
|
||||
break;
|
||||
case IAX_EVENT_VOICE:
|
||||
switch(e->event.voice.format) {
|
||||
case AST_FORMAT_GSM:
|
||||
if(e->event.voice.datalen % 33) {
|
||||
fprintf(stderr, "Weird gsm frame, not a multiple of 33.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!p->gsmin)
|
||||
p->gsmin = gsm_create();
|
||||
|
||||
len = 0;
|
||||
while(len < e->event.voice.datalen) {
|
||||
if(gsm_decode(p->gsmin, e->event.voice.data + len, fr)) {
|
||||
fprintf(stderr, "Bad GSM data\n");
|
||||
break;
|
||||
} else {
|
||||
int res;
|
||||
|
||||
res = write(audiofd, fr, sizeof(fr));
|
||||
if (res < 0)
|
||||
fprintf(f, "Write failed: %s\n", strerror(errno));
|
||||
}
|
||||
len += 33;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
fprintf(f, "Don't know how to handle that format %d\n", e->event.voice.format);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(f, "Unknown event: %d\n", e->etype);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dump_call(void)
|
||||
{
|
||||
if(most_recent_answer)
|
||||
{
|
||||
printf("Dumping call!\n");
|
||||
iax_hangup(most_recent_answer->session,"");
|
||||
free(most_recent_answer);
|
||||
}
|
||||
answered_call = 0;
|
||||
most_recent_answer = 0;
|
||||
answered_call = 0;
|
||||
peers = 0;
|
||||
newcall = 0;
|
||||
offhook = 0;
|
||||
ringing = 0;
|
||||
gentone(TONE_NONE, 0);
|
||||
}
|
||||
|
||||
void
|
||||
parse_cmd(FILE *f, int argc, char **argv)
|
||||
{
|
||||
if(!strcasecmp(argv[0], "HELP")) {
|
||||
if(argc == 1)
|
||||
dump_array(f, help);
|
||||
else if(argc == 2) {
|
||||
if(!strcasecmp(argv[1], "HELP"))
|
||||
fprintf(f, "Help <Command>\t-\tDisplays general help or specific help on command if supplied an arguement\n");
|
||||
else if(!strcasecmp(argv[1], "QUIT"))
|
||||
fprintf(f, "Quit\t\t-\tShuts down the miniphone\n");
|
||||
else fprintf(f, "No help available on %s\n", argv[1]);
|
||||
} else {
|
||||
fprintf(f, "Too many arguements for command help.\n");
|
||||
}
|
||||
} else if(!strcasecmp(argv[0], "STATUS")) {
|
||||
if(argc == 1) {
|
||||
int c = 0;
|
||||
struct peer *peerptr = peers;
|
||||
|
||||
if(!peerptr)
|
||||
fprintf(f, "No session matches found.\n");
|
||||
else while(peerptr) {
|
||||
fprintf(f, "Listing sessions:\n\n");
|
||||
fprintf(f, "Session %d\n", ++c);
|
||||
fprintf(f, "Session existed for %d seconds\n", (int)time(0)-peerptr->time);
|
||||
if(answered_call)
|
||||
fprintf(f, "Call answered.\n");
|
||||
else fprintf(f, "Call ringing.\n");
|
||||
|
||||
peerptr = peerptr->next;
|
||||
}
|
||||
} else fprintf(f, "Too many arguments for command status.\n");
|
||||
} else if(!strcasecmp(argv[0], "ANSWER")) {
|
||||
if(argc > 1)
|
||||
fprintf(f, "Too many arguements for command answer\n");
|
||||
else answer_call();
|
||||
} else if(!strcasecmp(argv[0], "REJECT")) {
|
||||
if(argc > 1)
|
||||
fprintf(f, "Too many arguements for command reject\n");
|
||||
else {
|
||||
fprintf(f, "Rejecting current phone call.\n");
|
||||
reject_call();
|
||||
}
|
||||
} else if (!strcasecmp(argv[0], "DUMP")) {
|
||||
dump_call();
|
||||
} else if (!strcasecmp(argv[0], "HANGUP")) {
|
||||
dump_call();
|
||||
} else if(!strcasecmp(argv[0], "CALL")) {
|
||||
if(argc > 2)
|
||||
fprintf(f, "Too many arguements for command call\n");
|
||||
else {
|
||||
call(f, argv[1]);
|
||||
}
|
||||
} else if(!strcasecmp(argv[0], "QUIT")) {
|
||||
if(argc > 1)
|
||||
fprintf(f, "Too many arguements for command quit\n");
|
||||
else {
|
||||
fprintf(f, "Good bye!\n");
|
||||
exit(1);
|
||||
}
|
||||
} else fprintf(f, "Unknown command of %s\n", argv[0]);
|
||||
}
|
||||
|
||||
void
|
||||
issue_prompt(FILE *f)
|
||||
{
|
||||
fprintf(f, "TeleClient> ");
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
void
|
||||
dump_array(FILE *f, char **array) {
|
||||
while(*array)
|
||||
fprintf(f, "%s\n", *array++);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#define RBUFSIZE 256
|
||||
#define MAXARGS 10
|
||||
#define MAXARG 256
|
||||
#define MAX_SESSIONS 4
|
||||
|
||||
extern void parse_cmd(FILE *, int, char **);
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Snomphone: IAX software for SNOM 100 Phone
|
||||
*
|
||||
* IAX Support for talking to Asterisk and other Gnophone clients
|
||||
*
|
||||
* Copyright (C) 1999, Linux Support Services, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#define CONFIG_FILE "/etc/miniphone.conf"
|
||||
#define USER_FILE "%s/.miniphone-conf"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char regpeer[256];
|
||||
char regsecret[256];
|
||||
char server[256];
|
||||
int refresh = 60;
|
||||
char context[256];
|
||||
char language[256];
|
||||
|
||||
#define TYPE_STRING 0
|
||||
#define TYPE_INT 1
|
||||
|
||||
struct opt {
|
||||
char *name;
|
||||
void *where;
|
||||
int len;
|
||||
int type;
|
||||
};
|
||||
|
||||
static struct opt opts[] = {
|
||||
{ "regpeer", regpeer, sizeof(regpeer), TYPE_STRING },
|
||||
{ "regsecret", regsecret, sizeof(regsecret), TYPE_STRING },
|
||||
{ "server", server, sizeof(server), TYPE_STRING },
|
||||
{ "context", context, sizeof(context), TYPE_STRING },
|
||||
{ "language", language, sizeof(language), TYPE_STRING },
|
||||
{ "refresh", &refresh, sizeof(refresh), TYPE_INT },
|
||||
};
|
||||
|
||||
static int __load_options(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
int lineno = 0;
|
||||
char buf[256];
|
||||
char *var, *value;
|
||||
int x;
|
||||
char *c;
|
||||
f = fopen(filename, "r");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Failed to open '%s': %s\n", filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
while(!feof(f)) {
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (!feof(f)) {
|
||||
/* Ditch comments */
|
||||
if ((c = strchr(buf, '#')))
|
||||
*c = 0;
|
||||
lineno++;
|
||||
/* Strip CR */
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
if (strlen(buf)) {
|
||||
var = strtok(buf, "=");
|
||||
value = strtok(NULL, "=");
|
||||
if (!var || !value) {
|
||||
fprintf(stderr, "Syntax error line %d\n", lineno);
|
||||
continue;
|
||||
}
|
||||
for (x=0;x<sizeof(opts) / sizeof(opts[0]); x++) {
|
||||
if (!strcasecmp(var, opts[x].name)) {
|
||||
switch(opts[x].type) {
|
||||
case TYPE_STRING:
|
||||
strncpy((char *)opts[x].where, value, opts[x].len);
|
||||
break;
|
||||
case TYPE_INT:
|
||||
if (sscanf(value, "%i", (int *)opts[x].where) != 1) {
|
||||
fprintf(stderr, "Not a number at line %d\n", lineno);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Don't know what to do about type %d\n", opts[x].type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(x < sizeof(opts) / sizeof(opts[0]))) {
|
||||
fprintf(stderr, "Dunno keyword '%s'\n", var);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_options(void)
|
||||
{
|
||||
char fn[256];
|
||||
__load_options(CONFIG_FILE);
|
||||
if (getenv("HOME")) {
|
||||
snprintf(fn, sizeof(fn), USER_FILE, getenv("HOME"));
|
||||
__load_options(fn);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __save_options(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
f = fopen(filename, "w");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Failed to open '%s': %s\n", filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int save_options(void)
|
||||
{
|
||||
char fn[256];
|
||||
if (getenv("HOME")) {
|
||||
snprintf(fn, sizeof(fn), USER_FILE, getenv("HOME"));
|
||||
return __save_options(fn);
|
||||
} else
|
||||
return __save_options(CONFIG_FILE);
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Snomphone: IAX software for SNOM 100 Phone
|
||||
*
|
||||
* IAX Support for talking to Asterisk and other Gnophone clients
|
||||
*
|
||||
* Copyright (C) 1999, Linux Support Services, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
extern char regpeer[256];
|
||||
extern char regsecret[256];
|
||||
extern char regpeer[256];
|
||||
extern char server[256];
|
||||
extern int refresh;
|
||||
extern char context[256];
|
||||
extern char language[256];
|
||||
|
||||
int save_options(void);
|
||||
int load_options(void);
|
||||
+1752
File diff suppressed because it is too large
Load Diff
+30
@@ -0,0 +1,30 @@
|
||||
/* ringtone.h: Generated from frequencies 440 and 480
|
||||
by gensound. 200 samples */
|
||||
static short ringtone[200] = {
|
||||
0, 11581, 21659, 28927, 32445, 31764, 26981, 18727,
|
||||
8084, -3559, -14693, -23875, -29927, -32083, -30088, -24228,
|
||||
-15290, -4453, 6864, 17195, 25212, 29902, 30693, 27526,
|
||||
20856, 11585, 944, -9673, -18899, -25560, -28837, -28357,
|
||||
-24244, -17089, -7868, 2192, 11780, 19667, 24872, 26779,
|
||||
25212, 20450, 13179, 4396, -4731, -13019, -19421, -23164,
|
||||
-23839, -21446, -16384, -9384, -1408, 6484, 13281, 18145,
|
||||
20517, 20182, 17286, 12301, 5951, -887, -7314, -12519,
|
||||
-15886, -17068, -16017, -12983, -8458, -3109, 2327, 7142,
|
||||
10750, 12757, 13007, 11585, 8793, 5095, 1044, -2800,
|
||||
-5951, -8053, -8921, -8560, -7141, -4967, -2421, 104,
|
||||
2260, 3791, 4567, 4589, 3977, 2941, 1733, 600,
|
||||
-257, -722, -772, -481, 0, 481, 772, 722,
|
||||
257, -600, -1733, -2941, -3977, -4589, -4567, -3791,
|
||||
-2260, -104, 2421, 4967, 7141, 8560, 8921, 8053,
|
||||
5951, 2800, -1044, -5095, -8793, -11585, -13007, -12757,
|
||||
-10750, -7142, -2327, 3109, 8458, 12983, 16017, 17068,
|
||||
15886, 12519, 7314, 887, -5951, -12301, -17286, -20182,
|
||||
-20517, -18145, -13281, -6484, 1408, 9384, 16384, 21446,
|
||||
23839, 23164, 19421, 13019, 4731, -4396, -13179, -20450,
|
||||
-25212, -26779, -24872, -19667, -11780, -2192, 7868, 17089,
|
||||
24244, 28357, 28837, 25560, 18899, 9673, -944, -11585,
|
||||
-20856, -27526, -30693, -29902, -25212, -17195, -6864, 4453,
|
||||
15290, 24228, 30088, 32083, 29927, 23875, 14693, 3559,
|
||||
-8084, -18727, -26981, -31764, -32445, -28927, -21659, -11581,
|
||||
|
||||
};
|
||||
+761
@@ -0,0 +1,761 @@
|
||||
/*
|
||||
* Miniphone: A simple, command line telephone
|
||||
*
|
||||
* IAX Support for talking to Asterisk and other Gnophone clients
|
||||
*
|
||||
* Copyright (C) 1999, Linux Support Services, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
/* #define PRINTCHUCK /* enable this to indicate chucked incomming packets */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
#include <mmsystem.h>
|
||||
#include <malloc.h>
|
||||
#include "gsm.h"
|
||||
#include "iax-client.h"
|
||||
#include "frame.h"
|
||||
#include "miniphone.h"
|
||||
|
||||
|
||||
struct peer {
|
||||
int time;
|
||||
gsm gsmin;
|
||||
gsm gsmout;
|
||||
|
||||
struct iax_session *session;
|
||||
struct peer *next;
|
||||
};
|
||||
|
||||
static struct peer *peers;
|
||||
static int answered_call = 0;
|
||||
|
||||
/* stuff for wave audio device */
|
||||
HWAVEOUT wout;
|
||||
HWAVEIN win;
|
||||
|
||||
typedef struct whout {
|
||||
WAVEHDR w;
|
||||
short data[160];
|
||||
struct whout *next;
|
||||
} WHOUT;
|
||||
|
||||
WHOUT *outqueue = NULL;
|
||||
|
||||
/* parameters for audio in */
|
||||
#define NWHIN 8 /* number of input buffer entries */
|
||||
/* NOTE the OUT_INTERVAL parameter *SHOULD* be more around 18 to 20 or so, since the packets should
|
||||
be spaced by 20 milliseconds. However, in practice, especially in Windoze-95, setting it that high
|
||||
caused underruns. 10 is just ever so slightly agressive, and the receiver has to chuck a packet
|
||||
every now and then. Thats about the way it should be to be happy. */
|
||||
#define OUT_INTERVAL 10 /* number of ms to wait before sending more data to peer */
|
||||
/* parameters for audio out */
|
||||
#define OUT_DEPTH 12 /* number of outbut buffer entries */
|
||||
#define OUT_PAUSE_THRESHOLD 2 /* number of active entries needed to start output (for smoothing) */
|
||||
|
||||
/* audio input buffer headers */
|
||||
WAVEHDR whin[NWHIN];
|
||||
/* audio input buffers */
|
||||
char bufin[NWHIN][320];
|
||||
|
||||
/* initialize the sequence variables for the audio in stuff */
|
||||
unsigned int whinserial = 1,nextwhin = 1;
|
||||
|
||||
static struct peer *find_peer(struct iax_session *);
|
||||
static void parse_args(FILE *, unsigned char *);
|
||||
void do_iax_event(FILE *);
|
||||
void call(FILE *, char *);
|
||||
void answer_call(void);
|
||||
void reject_call(void);
|
||||
static void handle_event(FILE *, struct iax_event *e, struct peer *p);
|
||||
void parse_cmd(FILE *, int, char **);
|
||||
void issue_prompt(FILE *);
|
||||
void dump_array(FILE *, char **);
|
||||
|
||||
static char *help[] = {
|
||||
"Welcome to the miniphone telephony client, the commands are as follows:\n",
|
||||
"Help\t\t-\tDisplays this screen.",
|
||||
"Call <Number>\t-\tDials the number supplied.",
|
||||
"Answer\t\t-\tAnswers an Inbound call.",
|
||||
"Reject\t\t-\tRejects an Inbound call.",
|
||||
"Dump\t\t-\tDumps (disconnects) the current call.",
|
||||
"Dtmf <Digit>\t-\tSends specified DTMF digit.",
|
||||
"Status\t\t-\tLists the current sessions and their current status.",
|
||||
"Quit\t\t-\tShuts down the client.",
|
||||
"",
|
||||
0
|
||||
};
|
||||
|
||||
static struct peer *most_recent_answer;
|
||||
static struct iax_session *newcall = 0;
|
||||
|
||||
/* holder of the time, relative to startup in system ticks. See our
|
||||
gettimeofday() implementation */
|
||||
time_t startuptime;
|
||||
|
||||
/* routine called at exit to shutdown audio I/O and close nicely.
|
||||
NOTE: If all this isnt done, the system doesnt not handle this
|
||||
cleanly and has to be rebooted. What a pile of doo doo!! */
|
||||
void killem(void)
|
||||
{
|
||||
waveInStop(win);
|
||||
waveInReset(win);
|
||||
waveInClose(win);
|
||||
waveOutReset(wout);
|
||||
waveOutClose(wout);
|
||||
WSACleanup(); /* dont forget socket stuff too */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Win-doze doenst have gettimeofday(). This sux. So, what we did is
|
||||
provide some gettimeofday-like functionality that works for our purposes.
|
||||
In the main(), we take a sample of the system tick counter (into startuptime).
|
||||
This function returns the relative time since program startup, more or less,
|
||||
which is certainly good enough for our purposes. */
|
||||
void gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
long l = startuptime + GetTickCount();
|
||||
|
||||
tv->tv_sec = l / 1000;
|
||||
tv->tv_usec = (l % 1000) * 1000;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static struct peer *find_peer(struct iax_session *session)
|
||||
{
|
||||
struct peer *cur = peers;
|
||||
while(cur) {
|
||||
if (cur->session == session)
|
||||
return cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
parse_args(FILE *f, unsigned char *cmd)
|
||||
{
|
||||
static char *argv[MAXARGS];
|
||||
unsigned char *parse = cmd;
|
||||
int argc = 0, t = 0;
|
||||
|
||||
// Don't mess with anything that doesn't exist...
|
||||
if(!*parse)
|
||||
return;
|
||||
|
||||
memset(argv, 0, sizeof(argv));
|
||||
while(*parse) {
|
||||
if(*parse < 33 || *parse > 128) {
|
||||
*parse = 0, t++;
|
||||
if(t > MAXARG) {
|
||||
fprintf(f, "Warning: Argument exceeds maximum argument size, command ignored!\n");
|
||||
return;
|
||||
}
|
||||
} else if(t || !argc) {
|
||||
if(argc == MAXARGS) {
|
||||
fprintf(f, "Warning: Command ignored, too many arguments\n");
|
||||
return;
|
||||
}
|
||||
argv[argc++] = parse;
|
||||
t = 0;
|
||||
}
|
||||
|
||||
parse++;
|
||||
}
|
||||
|
||||
if(argc)
|
||||
parse_cmd(f, argc, argv);
|
||||
}
|
||||
|
||||
/* handle all network requests, and a pending scheduled event, if any */
|
||||
void service_network(int netfd, FILE *f)
|
||||
{
|
||||
fd_set readfd;
|
||||
struct timeval dumbtimer;
|
||||
|
||||
/* set up a timer that falls-through */
|
||||
dumbtimer.tv_sec = 0;
|
||||
dumbtimer.tv_usec = 0;
|
||||
|
||||
|
||||
for(;;) /* suck everything outa network stuff */
|
||||
{
|
||||
FD_ZERO(&readfd);
|
||||
FD_SET(netfd, &readfd);
|
||||
if (select(netfd + 1, &readfd, 0, 0, &dumbtimer) > 0)
|
||||
{
|
||||
if (FD_ISSET(netfd,&readfd))
|
||||
{
|
||||
do_iax_event(f);
|
||||
(void) iax_time_to_next_event();
|
||||
} else break;
|
||||
} else break;
|
||||
}
|
||||
do_iax_event(f); /* do pending event if any */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int port;
|
||||
int netfd;
|
||||
int c, i;
|
||||
FILE *f;
|
||||
char rcmd[RBUFSIZE];
|
||||
gsm_frame fo;
|
||||
WSADATA foop;
|
||||
time_t t;
|
||||
WAVEFORMATEX wf;
|
||||
WHOUT *wh,*wh1,*wh2;
|
||||
unsigned long lastouttick = 0;
|
||||
|
||||
|
||||
|
||||
/* get time of day in milliseconds, offset by tick count (see our
|
||||
gettimeofday() implementation) */
|
||||
time(&t);
|
||||
startuptime = ((t % 86400) * 1000) - GetTickCount();
|
||||
|
||||
f = stdout;
|
||||
_dup2(fileno(stdout),fileno(stderr));
|
||||
|
||||
/* start up the windoze-socket layer stuff */
|
||||
if (WSAStartup(0x0101,&foop)) {
|
||||
fprintf(stderr,"Fatal error: Falied to startup windows sockets\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* setup the format for opening audio channels */
|
||||
wf.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wf.nChannels = 1;
|
||||
wf.nSamplesPerSec = 8000;
|
||||
wf.nAvgBytesPerSec = 16000;
|
||||
wf.nBlockAlign = 2;
|
||||
wf.wBitsPerSample = 16;
|
||||
wf.cbSize = 0;
|
||||
/* open the audio out channel */
|
||||
if (waveOutOpen(&wout,0,&wf,0,0,CALLBACK_NULL) != MMSYSERR_NOERROR)
|
||||
{
|
||||
fprintf(stderr,"Fatal Error: Failed to open wave output device\n");
|
||||
return -1;
|
||||
}
|
||||
/* open the audio in channel */
|
||||
if (waveInOpen(&win,0,&wf,0,0,CALLBACK_NULL) != MMSYSERR_NOERROR)
|
||||
{
|
||||
fprintf(stderr,"Fatal Error: Failed to open wave input device\n");
|
||||
waveOutReset(wout);
|
||||
waveOutClose(wout);
|
||||
return -1;
|
||||
}
|
||||
/* activate the exit handler */
|
||||
atexit(killem);
|
||||
/* initialize the audio in buffer structures */
|
||||
memset(&whin,0,sizeof(whin));
|
||||
|
||||
if ( (port = iax_init(0) < 0)) {
|
||||
fprintf(stderr, "Fatal error: failed to initialize iax with port %d\n", port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
iax_set_formats(AST_FORMAT_GSM);
|
||||
netfd = iax_get_fd();
|
||||
|
||||
fprintf(f, "Text Based Telephony Client.\n\n");
|
||||
issue_prompt(f);
|
||||
|
||||
/* main tight loop */
|
||||
while(1) {
|
||||
/* service the network stuff */
|
||||
service_network(netfd,f);
|
||||
if (outqueue) /* if stuff in audio output queue, free it up if its available */
|
||||
{
|
||||
/* go through audio output queue */
|
||||
for(wh = outqueue,wh1 = wh2 = NULL,i = 0; wh != NULL; wh = wh->next)
|
||||
{
|
||||
service_network(netfd,f); /* service network here for better performance */
|
||||
/* if last one was removed from queue, zot it here */
|
||||
if (i && wh1)
|
||||
{
|
||||
free(wh1);
|
||||
wh1 = wh2;
|
||||
}
|
||||
i = 0; /* reset "last one removed" flag */
|
||||
if (wh->w.dwFlags & WHDR_DONE) /* if this one is done */
|
||||
{
|
||||
/* prepare audio header */
|
||||
if ((c = waveOutUnprepareHeader(wout,&wh->w,sizeof(WAVEHDR))) != MMSYSERR_NOERROR)
|
||||
{
|
||||
fprintf(stderr,"Cannot unprepare audio out header, error %d\n",c);
|
||||
exit(255);
|
||||
}
|
||||
if (wh1 != NULL) /* if there was a last one */
|
||||
{
|
||||
wh1->next = wh->next;
|
||||
}
|
||||
if (outqueue == wh) /* is first one, so set outqueue to next one */
|
||||
{
|
||||
outqueue = wh->next;
|
||||
}
|
||||
i = 1; /* set 'to free' flag */
|
||||
}
|
||||
wh2 = wh1; /* save old,old wh pointer */
|
||||
wh1 = wh; /* save the old wh pointer */
|
||||
}
|
||||
}
|
||||
/* go through all audio in buffers, and prepare and queue ones that are currently idle */
|
||||
for(i = 0; i < NWHIN; i++)
|
||||
{
|
||||
service_network(netfd,f); /* service network stuff here for better performance */
|
||||
if (!(whin[i].dwFlags & WHDR_PREPARED)) /* if not prepared, do so */
|
||||
{
|
||||
/* setup this input buffer header */
|
||||
memset(&whin[i],0,sizeof(WAVEHDR));
|
||||
whin[i].lpData = bufin[i];
|
||||
whin[i].dwBufferLength = 320;
|
||||
whin[i].dwUser = whinserial++; /* set 'user data' to current serial number */
|
||||
/* prepare the buffer */
|
||||
if (waveInPrepareHeader(win,&whin[i],sizeof(WAVEHDR)))
|
||||
{
|
||||
fprintf(stderr,"Unable to prepare header for input\n");
|
||||
return -1;
|
||||
}
|
||||
/* add it to device (queue) */
|
||||
if (waveInAddBuffer(win,&whin[i],sizeof(WAVEHDR)))
|
||||
{
|
||||
fprintf(stderr,"Unable to prepare header for input\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
waveInStart(win); /* start it (if not already started) */
|
||||
}
|
||||
|
||||
/* if key pressed, do command stuff */
|
||||
if(_kbhit())
|
||||
{
|
||||
if ( ( fgets(&*rcmd, 256, stdin))) {
|
||||
rcmd[strlen(rcmd)-1] = 0;
|
||||
parse_args(f, &*rcmd);
|
||||
} else fprintf(f, "Fatal error: failed to read data!\n");
|
||||
|
||||
issue_prompt(f);
|
||||
}
|
||||
/* do audio input stuff for buffers that have received data from audio in device already. Must
|
||||
do them in serial number order (the order in which they were originally queued). */
|
||||
if(answered_call) /* send audio only if call answered */
|
||||
{
|
||||
for(;;) /* loop until all are found */
|
||||
{
|
||||
for(i = 0; i < NWHIN; i++) /* find an available one that's the one we are looking for */
|
||||
{
|
||||
service_network(netfd,f); /* service network here for better performance */
|
||||
/* if not time to send any more, dont */
|
||||
if (GetTickCount() < (lastouttick + OUT_INTERVAL))
|
||||
{
|
||||
i = NWHIN; /* set to value that WILL exit loop */
|
||||
break;
|
||||
}
|
||||
if ((whin[i].dwUser == nextwhin) && (whin[i].dwFlags & WHDR_DONE)) { /* if audio is ready */
|
||||
|
||||
/* must have read exactly 320 bytes */
|
||||
if (whin[i].dwBytesRecorded != whin[i].dwBufferLength)
|
||||
{
|
||||
fprintf(stderr,"Short audio read, got %d bytes, expected %d bytes\n", whin[i].dwBytesRecorded,
|
||||
whin[i].dwBufferLength);
|
||||
return -1;
|
||||
}
|
||||
if(!most_recent_answer->gsmout)
|
||||
most_recent_answer->gsmout = gsm_create();
|
||||
|
||||
service_network(netfd,f); /* service network here for better performance */
|
||||
/* encode the audio from the buffer into GSM format */
|
||||
gsm_encode(most_recent_answer->gsmout, (short *) ((char *) whin[i].lpData), fo);
|
||||
if(iax_send_voice(most_recent_answer->session,
|
||||
AST_FORMAT_GSM, (char *)fo, sizeof(gsm_frame)) == -1)
|
||||
puts("Failed to send voice!");
|
||||
lastouttick = GetTickCount(); /* save time of last output */
|
||||
|
||||
/* unprepare (free) the header */
|
||||
waveInUnprepareHeader(win,&whin[i],sizeof(WAVEHDR));
|
||||
/* initialize the buffer */
|
||||
memset(&whin[i],0,sizeof(WAVEHDR));
|
||||
/* bump the serial number to look for the next time */
|
||||
nextwhin++;
|
||||
/* exit the loop so that we can start at lowest buffer again */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= NWHIN) break; /* if all found, get out of loop */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
do_iax_event(FILE *f) {
|
||||
int sessions = 0;
|
||||
struct iax_event *e = 0;
|
||||
struct peer *peer;
|
||||
|
||||
while ( (e = iax_get_event(0))) {
|
||||
peer = find_peer(e->session);
|
||||
if(peer) {
|
||||
handle_event(f, e, peer);
|
||||
} else {
|
||||
if(e->etype != IAX_EVENT_CONNECT) {
|
||||
fprintf(stderr, "Huh? This is an event for a non-existant session?\n");
|
||||
}
|
||||
sessions++;
|
||||
|
||||
if(sessions >= MAX_SESSIONS) {
|
||||
fprintf(f, "Missed a call... too many sessions open.\n");
|
||||
}
|
||||
|
||||
|
||||
if(e->event.connect.callerid && e->event.connect.dnid)
|
||||
fprintf(f, "Call from '%s' for '%s'", e->event.connect.callerid,
|
||||
e->event.connect.dnid);
|
||||
else if(e->event.connect.dnid) {
|
||||
fprintf(f, "Call from '%s'", e->event.connect.dnid);
|
||||
} else if(e->event.connect.callerid) {
|
||||
fprintf(f, "Call from '%s'", e->event.connect.callerid);
|
||||
} else printf("Call from");
|
||||
fprintf(f, " (%s)\n", inet_ntoa(iax_get_peer_addr(e->session).sin_addr));
|
||||
|
||||
if(most_recent_answer) {
|
||||
fprintf(f, "Incoming call ignored, there's already a call waiting for answer... \
|
||||
please accept or reject first\n");
|
||||
iax_reject(e->session, "Too many calls, we're busy!");
|
||||
} else {
|
||||
if ( !(peer = malloc(sizeof(struct peer)))) {
|
||||
fprintf(f, "Warning: Unable to allocate memory!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
peer->time = time(0);
|
||||
peer->session = e->session;
|
||||
peer->gsmin = 0;
|
||||
peer->gsmout = 0;
|
||||
|
||||
peer->next = peers;
|
||||
peers = peer;
|
||||
|
||||
iax_accept(peer->session);
|
||||
iax_ring_announce(peer->session);
|
||||
most_recent_answer = peer;
|
||||
fprintf(f, "Incoming call!\n");
|
||||
}
|
||||
iax_event_free(e);
|
||||
issue_prompt(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
call(FILE *f, char *num)
|
||||
{
|
||||
struct peer *peer;
|
||||
|
||||
if(!newcall)
|
||||
newcall = iax_session_new();
|
||||
else {
|
||||
fprintf(f, "Already attempting to call somewhere, please cancel first!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !(peer = malloc(sizeof(struct peer)))) {
|
||||
fprintf(f, "Warning: Unable to allocate memory!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
peer->time = time(0);
|
||||
peer->session = newcall;
|
||||
peer->gsmin = 0;
|
||||
peer->gsmout = 0;
|
||||
|
||||
peer->next = peers;
|
||||
peers = peer;
|
||||
|
||||
most_recent_answer = peer;
|
||||
|
||||
iax_call(peer->session, num, 10);
|
||||
}
|
||||
|
||||
void
|
||||
answer_call(void)
|
||||
{
|
||||
if(most_recent_answer)
|
||||
iax_answer(most_recent_answer->session);
|
||||
printf("Answering call!\n");
|
||||
answered_call = 1;
|
||||
}
|
||||
|
||||
void
|
||||
dump_call(void)
|
||||
{
|
||||
if(most_recent_answer)
|
||||
{
|
||||
iax_hangup(most_recent_answer->session,"");
|
||||
free(most_recent_answer);
|
||||
}
|
||||
printf("Dumping call!\n");
|
||||
answered_call = 0;
|
||||
most_recent_answer = 0;
|
||||
answered_call = 0;
|
||||
peers = 0;
|
||||
newcall = 0;
|
||||
}
|
||||
|
||||
void
|
||||
reject_call(void)
|
||||
{
|
||||
iax_reject(most_recent_answer->session, "Call rejected manually.");
|
||||
most_recent_answer = 0;
|
||||
}
|
||||
|
||||
void
|
||||
handle_event(FILE *f, struct iax_event *e, struct peer *p)
|
||||
{
|
||||
int len,n;
|
||||
WHOUT *wh,*wh1;
|
||||
short fr[160];
|
||||
static paused_xmit = 0;
|
||||
|
||||
|
||||
switch(e->etype) {
|
||||
case IAX_EVENT_HANGUP:
|
||||
iax_hangup(most_recent_answer->session, "Byeee!");
|
||||
fprintf(f, "Call disconnected by peer\n");
|
||||
free(most_recent_answer);
|
||||
most_recent_answer = 0;
|
||||
answered_call = 0;
|
||||
peers = 0;
|
||||
newcall = 0;
|
||||
|
||||
break;
|
||||
|
||||
case IAX_EVENT_REJECT:
|
||||
fprintf(f, "Authentication was rejected\n");
|
||||
break;
|
||||
case IAX_EVENT_ACCEPT:
|
||||
fprintf(f, "Waiting for answer... RING RING\n");
|
||||
issue_prompt(f);
|
||||
break;
|
||||
case IAX_EVENT_ANSWER:
|
||||
answer_call();
|
||||
break;
|
||||
case IAX_EVENT_VOICE:
|
||||
switch(e->event.voice.format) {
|
||||
case AST_FORMAT_GSM:
|
||||
if(e->event.voice.datalen % 33) {
|
||||
fprintf(stderr, "Weird gsm frame, not a multiple of 33.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!p->gsmin)
|
||||
p->gsmin = gsm_create();
|
||||
|
||||
len = 0;
|
||||
while(len < e->event.voice.datalen) {
|
||||
if(gsm_decode(p->gsmin, (char *) e->event.voice.data + len, fr)) {
|
||||
fprintf(stderr, "Bad GSM data\n");
|
||||
break;
|
||||
} else { /* its an audio packet to be output to user */
|
||||
|
||||
/* get count of pending items in audio output queue */
|
||||
n = 0;
|
||||
if (outqueue)
|
||||
{ /* determine number of pending out queue items */
|
||||
for(wh = outqueue; wh != NULL; wh = wh->next)
|
||||
{
|
||||
if (!(wh->w.dwFlags & WHDR_DONE)) n++;
|
||||
}
|
||||
}
|
||||
/* if not too many, send to user, otherwise chuck packet */
|
||||
if (n <= OUT_DEPTH) /* if not to chuck packet */
|
||||
{
|
||||
/* malloc the memory for the queue item */
|
||||
wh = (WHOUT *) malloc(sizeof(WHOUT));
|
||||
if (wh == (WHOUT *) NULL) /* if error, bail */
|
||||
{
|
||||
fprintf(stderr,"Outa memory!!!!\n");
|
||||
exit(255);
|
||||
}
|
||||
/* initialize the queue entry */
|
||||
memset(wh,0,sizeof(WHOUT));
|
||||
/* copy the PCM data from the gsm conversion buffer */
|
||||
memcpy((char *)wh->data,(char *)fr,sizeof(fr));
|
||||
/* set parameters for data */
|
||||
wh->w.lpData = (char *) wh->data;
|
||||
wh->w.dwBufferLength = 320;
|
||||
|
||||
/* prepare buffer for output */
|
||||
if (waveOutPrepareHeader(wout,&wh->w,sizeof(WAVEHDR)))
|
||||
{
|
||||
fprintf(stderr,"Cannot prepare header for audio out\n");
|
||||
exit(255);
|
||||
}
|
||||
/* if not currently transmitting, hold off a couple of packets for
|
||||
smooth sounding output */
|
||||
if ((!n) && (!paused_xmit))
|
||||
{
|
||||
/* pause output (before starting) */
|
||||
waveOutPause(wout);
|
||||
/* indicate as such */
|
||||
paused_xmit = 1;
|
||||
}
|
||||
/* queue packet for output on audio device */
|
||||
if (waveOutWrite(wout,&wh->w,sizeof(WAVEHDR)))
|
||||
{
|
||||
fprintf(stderr,"Cannot output to wave output device\n");
|
||||
exit(255);
|
||||
}
|
||||
/* if we are paused, and we have enough packets, start audio */
|
||||
if ((n > OUT_PAUSE_THRESHOLD) && paused_xmit)
|
||||
{
|
||||
/* start the output */
|
||||
waveOutRestart(wout);
|
||||
/* indicate as such */
|
||||
paused_xmit = 0;
|
||||
}
|
||||
/* insert it onto tail of outqueue */
|
||||
if (outqueue == NULL) /* if empty queue */
|
||||
outqueue = wh; /* point queue to new entry */
|
||||
else /* otherwise is non-empty queue */
|
||||
{
|
||||
wh1 = outqueue;
|
||||
while(wh1->next) wh1 = wh1->next; /* find last entry in queue */
|
||||
wh1->next = wh; /* point it to new entry */
|
||||
}
|
||||
}
|
||||
#ifdef PRINTCHUCK
|
||||
else printf("Chucking packet!!\n");
|
||||
#endif
|
||||
}
|
||||
len += 33;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
fprintf(f, "Don't know how to handle that format %d\n", e->event.voice.format);
|
||||
}
|
||||
break;
|
||||
case IAX_EVENT_RINGA:
|
||||
break;
|
||||
default:
|
||||
fprintf(f, "Unknown event: %d\n", e->etype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse_cmd(FILE *f, int argc, char **argv)
|
||||
{
|
||||
_strupr(argv[0]);
|
||||
if(!strcmp(argv[0], "HELP")) {
|
||||
if(argc == 1)
|
||||
dump_array(f, help);
|
||||
else if(argc == 2) {
|
||||
if(!strcmp(argv[1], "HELP"))
|
||||
fprintf(f, "Help <Command>\t-\tDisplays general help or specific help on command if supplied an arguement\n");
|
||||
else if(!strcmp(argv[1], "QUIT"))
|
||||
fprintf(f, "Quit\t\t-\tShuts down the miniphone\n");
|
||||
else fprintf(f, "No help available on %s\n", argv[1]);
|
||||
} else {
|
||||
fprintf(f, "Too many arguements for command help.\n");
|
||||
}
|
||||
} else if(!strcmp(argv[0], "STATUS")) {
|
||||
if(argc == 1) {
|
||||
int c = 0;
|
||||
struct peer *peerptr = peers;
|
||||
|
||||
if(!peerptr)
|
||||
fprintf(f, "No session matches found.\n");
|
||||
else while(peerptr) {
|
||||
fprintf(f, "Listing sessions:\n\n");
|
||||
fprintf(f, "Session %d\n", ++c);
|
||||
fprintf(f, "Session existed for %d seconds\n", (int)time(0)-peerptr->time);
|
||||
if(answered_call)
|
||||
fprintf(f, "Call answered.\n");
|
||||
else fprintf(f, "Call ringing.\n");
|
||||
|
||||
peerptr = peerptr->next;
|
||||
}
|
||||
} else fprintf(f, "Too many arguments for command status.\n");
|
||||
} else if(!strcmp(argv[0], "ANSWER")) {
|
||||
if(argc > 1)
|
||||
fprintf(f, "Too many arguements for command answer\n");
|
||||
else answer_call();
|
||||
} else if(!strcmp(argv[0], "REJECT")) {
|
||||
if(argc > 1)
|
||||
fprintf(f, "Too many arguements for command reject\n");
|
||||
else {
|
||||
fprintf(f, "Rejecting current phone call.\n");
|
||||
reject_call();
|
||||
}
|
||||
} else if(!strcmp(argv[0], "CALL")) {
|
||||
if(argc > 2)
|
||||
fprintf(f, "Too many arguements for command call\n");
|
||||
else {
|
||||
call(f, argv[1]);
|
||||
}
|
||||
} else if(!strcmp(argv[0], "DUMP")) {
|
||||
if(argc > 1)
|
||||
fprintf(f, "Too many arguements for command dump\n");
|
||||
else {
|
||||
dump_call();
|
||||
}
|
||||
} else if(!strcmp(argv[0], "DTMF")) {
|
||||
if(argc > 2)
|
||||
{
|
||||
fprintf(f, "Too many arguements for command dtmf\n");
|
||||
return;
|
||||
}
|
||||
if (argc < 1)
|
||||
{
|
||||
fprintf(f, "Too many arguements for command dtmf\n");
|
||||
return;
|
||||
}
|
||||
if(most_recent_answer)
|
||||
iax_send_dtmf(most_recent_answer->session,*argv[1]);
|
||||
} else if(!strcmp(argv[0], "QUIT")) {
|
||||
if(argc > 1)
|
||||
fprintf(f, "Too many arguements for command quit\n");
|
||||
else {
|
||||
fprintf(f, "Good bye!\n");
|
||||
exit(1);
|
||||
}
|
||||
} else fprintf(f, "Unknown command of %s\n", argv[0]);
|
||||
}
|
||||
|
||||
void
|
||||
issue_prompt(FILE *f)
|
||||
{
|
||||
fprintf(f, "TeleClient> ");
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
void
|
||||
dump_array(FILE *f, char **array) {
|
||||
while(*array)
|
||||
fprintf(f, "%s\n", *array++);
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Functions Windows doesn't have... but should
|
||||
* Copyright(C) 2001, Linux Support Services, Inc.
|
||||
*
|
||||
* Distributed under GNU LGPL.
|
||||
*
|
||||
* These are NOT fully compliant with BSD 4.3 and are not
|
||||
* threadsafe.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _winpoop_h
|
||||
#define _winpoop_h
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define INLINE __inline
|
||||
#define inline __inline
|
||||
|
||||
#if _MSC_VER < 1900
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
// should try without these
|
||||
#pragma warning(disable: 4996 4244 4305 4018 4804)
|
||||
#if defined(_WIN64)
|
||||
typedef __int64 ssize_t;
|
||||
#elif defined(_WIN32)
|
||||
typedef __int32 ssize_t;
|
||||
#endif
|
||||
#else
|
||||
#define INLINE inline
|
||||
#endif
|
||||
|
||||
#include <winsock2.h> // this include <windows.h>
|
||||
#include <io.h> // for open, close, write, read
|
||||
#include <stdio.h>
|
||||
|
||||
void gettimeofday(struct timeval *tv, void /*struct timezone*/ *tz);
|
||||
|
||||
static INLINE int inet_aton(char *cp, struct in_addr *inp)
|
||||
{
|
||||
int a1, a2, a3, a4;
|
||||
unsigned int saddr;
|
||||
|
||||
if (sscanf(cp, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) != 4)
|
||||
return 0;
|
||||
a1 &= 0xff;
|
||||
a2 &= 0xff;
|
||||
a3 &= 0xff;
|
||||
a4 &= 0xff;
|
||||
saddr = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4;
|
||||
inp->s_addr = htonl(saddr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
+4350
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user