add libsndfile directory

git-svn-id: svn://localhost/ardour2/trunk@583 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis
2006-06-14 17:05:39 +00:00
parent eac4dc101d
commit 81486cf7bd
110 changed files with 67562 additions and 0 deletions

14
libs/libsndfile/AUTHORS Normal file
View File

@@ -0,0 +1,14 @@
The main author of libsndfile is Erik de Castro Lopo <erikd@mega-nerd.com>.
The code in the src/GSM610 directory was written by Jutta Degener
<jutta@cs.tu-berlin.de> and Carsten Bormann <cabo@cs.tu-berlin.de>.
They should not be contacted in relation to libsndfile or the GSM 6.10 code
that is part of libsndfile. Their original code can be found at:
http://kbs.cs.tu-berlin.de/~jutta/toast.html
Code in the src/G72x directory was released by Sun Microsystems, Inc. to the
public domain. Minor modifications were required to integrate these files
into libsndfile. The changes are listed in src/G72x/ChangeLog.

6107
libs/libsndfile/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
#!/bin/sh
# Copyright (C) 2006 Erik de Castro Lopo <erikd@mega-nerd.com>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the author nor the names of any contributors may be used
# to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -e
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
echo "Usage : Mingw-make-dist.sh <source tarball>."
exit 1
fi
TARGZ=$1
if [ ! -f $TARGZ ]; then
echo "Can't find source tarball."
fi
TARGZ=$1
if [ ! -f $TARGZ.asc ]; then
echo "Can't find source tarball signature."
fi
UNAME=`uname -s`
if [ x$UNAME != "xMINGW32_NT-5.1" ]; then
echo "Not able to build Win32 binaries on this platform."
fi
echo "Building MinGW binary/source zip file."
VERSION=`pwd | sed -e "s#.*/##" | sed -e s/libsndfile-//`
BUILD=`echo $VERSION | sed -e "s/\./_/g"`
INSTALL="libsndfile-$BUILD"
ZIPNAME="$INSTALL.zip"
if [ -z "$BUILD" ]; then
echo "Bad BUILD variable : '$BUILD'"
exit 1
fi
if [ ! -d $INSTALL/ ]; then
mkdir $INSTALL
fi
if [ ! -f config.status ]; then
./configure --prefix=`pwd`/$INSTALL/
else
teststr=`grep "with options" config.status | grep -- --prefix=`
if [ -z "$teststr" ]; then
# --disable-static doesn't work.
./configure --prefix=`pwd`/$INSTALL/
fi
fi
if [ ! -f src/.libs/libsndfile-1.dll ]; then
make all check
fi
if [ ! -f $INSTALL/bin/libsndfile-1.dll ]; then
make install
rm -f $INSTALL/bin/sndfile-regtest.exe
strip $INSTALL/bin/*.*
mv $INSTALL/bin/*.* $INSTALL/include/*.* $INSTALL/
rmdir $INSTALL/bin
rm -rf $INSTALL/lib
rmdir $INSTALL/include
cp src/libsndfile.def $INSTALL/
cp Win32/README-precompiled-dll.txt $INSTALL/
fi
if [ ! -f $INSTALL/libsndfile-$VERSION.tar.gz ]; then
cp $TARGZ $INSTALL/
if [ -f $TARGZ.asc ]; then
cp $TARGZ.asc $INSTALL/
fi
fi
if [ ! -f $ZIPNAME ]; then
zip -r $ZIPNAME $INSTALL/
fi
# Do not edit or modify anything in this comment block.
# The following line is a file identity tag for the GNU Arch
# revision control system.
#
# arch-tag: 3f82cd8a-f800-48d7-9646-2cdcf03c81a0

126
libs/libsndfile/NEWS Normal file
View File

@@ -0,0 +1,126 @@
Version 1.0.16 (2006-04-30)
* Add support for Broadcast (BEXT) chunks in WAV files.
* Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS.
* Add support for RIFX (big endian WAV variant).
* Fix configure script bugs.
* Fix bug in INST and MARK chunk writing for AIFF files.
Version 1.0.15 (2006-03-16)
* Fix some ia64 issues.
* Fix precompiled DLL.
* Minor bug fixes.
Version 1.0.14 (2006-02-19)
* Really fix MinGW compile problems.
* Minor bug fixes.
Version 1.0.13 (2006-01-21)
* Fix for MinGW compiler problems.
* Allow readin/write of instrument chunks from WAV and AIFF files.
* Compile problem fix for Solaris compiler.
* Minor cleanups and bug fixes.
Version 1.0.12 (2005-09-30)
* Add support for FLAC and Apple's Core Audio Format (CAF).
* Add virtual I/O interface (still needs docs).
* Cygwin and other Win32 fixes.
* Minor bug fixes and cleanups.
Version 1.0.11 (2004-11-15)
* Add support for SD2 files.
* Add read support for loop info in WAV and AIFF files.
* Add more tests.
* Improve type safety.
* Minor optimisations and bug fixes.
Version 1.0.10 (2004-06-15)
* Fix AIFF read/write mode bugs.
* Add support for compiling Win32 DLLS using MinGW.
* Fix problems resulting in failed compiles with gcc-2.95.
* Improve test suite.
* Minor bug fixes.
Version 1.0.9 (2004-03-30)
* Add handling of AVR (Audio Visual Research) files.
* Improve handling of WAVEFORMATEXTENSIBLE WAV files.
* Fix for using pipes on Win32.
Version 1.0.8 (2004-03-14)
* Correct peak chunk handing for files with > 16 tracks.
* Fix for WAV files with huge number of CUE chunks.
Version 1.0.7 (2004-02-25)
* Fix clip mode detection on ia64, MIPS and other CPUs.
* Fix two MacOSX build problems.
Version 1.0.6 (2004-02-08)
* Added support for native Win32 file access API (Ross Bencina).
* New mode to add clippling then a converting from float/double to integer
would otherwise wrap around.
* Fixed a bug in reading/writing files > 2Gig on Linux, Solaris and others.
* Many minor bug fixes.
* Other random fixes for Win32.
Version 1.0.5 (2003-05-03)
* Added support for HTK files.
* Added new function sf_open_fd() to allow for secure opening of temporary
files as well as reading/writing sound files embedded within larger
container files.
* Added string support for AIFF files.
* Minor bug fixes and code cleanups.
Version 1.0.4 (2003-02-02)
* Added suport of PVF and XI files.
* Added functionality for setting and retreiving strings from sound files.
* Minor code cleanups and bug fixes.
Version 1.0.3 (2002-12-09)
* Minor bug fixes.
Version 1.0.2 (2002-11-24)
* Added support for VOX ADPCM.
* Improved error reporting.
* Added version scripting on Linux and Solaris.
* Minor bug fixes.
Version 1.0.1 (2002-09-14)
* Added MAT and MAT5 file formats.
* Minor bug fixes.
Version 1.0.0 (2002-08-16)
* Final release for 1.0.0.
Version 1.0.0rc6 (2002-08-14)
* Release candidate 6 for the 1.0.0 series.
* MacOS9 fixes.
Version 1.0.0rc5 (2002-08-10)
* Release candidate 5 for the 1.0.0 series.
* Changed the definition of sf_count_t which was causing problems when
libsndfile was compiled with other libraries (ie WxWindows).
* Minor bug fixes.
* Documentation cleanup.
Version 1.0.0rc4 (2002-08-03)
* Release candidate 4 for the 1.0.0 series.
* Minor bug fixes.
* Fix broken Win32 "make check".
Version 1.0.0rc3 (2002-08-02)
* Release candidate 3 for the 1.0.0 series.
* Fix bug where libsndfile was reading beyond the end of the data chunk.
* Added on-the-fly header updates on write.
* Fix a couple of documentation issues.
Version 1.0.0rc2 (2002-06-24)
* Release candidate 2 for the 1.0.0 series.
* Fix compile problem for Win32.
Version 1.0.0rc1 (2002-06-24)
* Release candidate 1 for the 1.0.0 series.
Version 0.0.28 (2002-04-27)
* Last offical release of 0.0.X series of the library.
Version 0.0.8 (1999-02-16)
* First offical release.

71
libs/libsndfile/README Normal file
View File

@@ -0,0 +1,71 @@
This is libsndfile, 1.0.16
libsndfile is a library of C routines for reading and writing
files containing sampled audio data.
The src/ directory contains the source code for library itself.
The doc/ directory contains the libsndfile documentation.
The examples/ directory contains examples of how to write code using
libsndfile. 'wav32_aiff24' converts a WAV file containing 32 bit floating
point data into a 24 bit PCM AIFF file. 'sndfile2oct' dumps the audio
data of a file in a human readable format. 'sfconvert' is the beginnings
of a audio file format conversion utility. 'make_sine' generates a WAV
file containing one cycle of a sine wave with 4096 sample points in
32 bit floating point format. 'sfinfo' opens a sound file and prints
out information about that file.
The tests/ directory contains programs which link against libsndfile
and test its functionality.
The Win32/ directory contains files and documentation to allow libsndfile
to compile under Win32 with the Microsoft Visual C++ compiler.
The src/GSM610 directory contains code written by Jutta Degener and Carsten
Bormann. Their original code can be found at :
http://kbs.cs.tu-berlin.de/~jutta/toast.html
The src/G72x directory contains code written and released by Sun Microsystems
under a suitably free license.
Win32
-----
There are detailed instructions for building libsndfile on Win32 in the file
doc/win32.html
MacOSX
------
Building on MacOSX should be the same as building it on any other Unix.
OTHER PLATFORMS
---------------
To compile libsndfile on platforms which have a Bourne Shell compatible
shell, an ANSI C compiler and a make utility should require no more that
the following three commands :
./configure
make
make install
For platforms without the required shell, it is usually sufficient to
create an approriate config.h file in the src/ directory with correct
values for the following #defines (this would work for AmigaOS) :
#define HAVE_ENDIAN_H 0
#define GUESS_BIG_ENDIAN 1
#define GUESS_LITTLE_ENDIAN 0
#define FORCE_BROKEN_FLOAT 0
CONTACTS
--------
libsndfile was written by Erik de Castro Lopo (erikd AT mega-nerd DOT com).
The libsndfile home page is at :
http://www.mega-nerd.com/libsndfile/

View File

@@ -0,0 +1,36 @@
# -*- python -*-
import os
import os.path
import glob
sndfile_files = glob.glob('src/*.c') + glob.glob('src/GSM610/*.c') + glob.glob('src/G72x/*.c')
Import('env install_prefix')
sndfile = env.Copy()
domain = 'libsndfile'
sndfile.Append(CCFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
sndfile.Append(CCFLAGS = "-DVERSION=\\\"ardour-special\\\"")
# mingw may need this
#sndfile.Append(CCFLAGS="-no-undefined")
sndfile.Append(PACKAGE = domain)
sndfile.Append(POTFILE = domain + '.pot')
libsndfile = sndfile.SharedLibrary('sndfile', sndfile_files)
sndfile_h = sndfile.Command('src/sndfile.h', ['src/sndfile.h.in'], 'cd libs/libsndfile && ./configure && cd -', ENV=os.environ)
Default([sndfile_h,libsndfile])
env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libsndfile))
env.Alias('tarball', env.Distribute (env['DISTTREE'],
[ 'NEWS', 'README', 'AUTHORS', 'ChangeLog',
'configure', 'SConscript',] +
sndfile_files +
glob.glob('src/*.h') +
[ 'src/sndfile.h.in', 'src/config.h.in', 'src/Symbols.linux', 'src/Symbols.darwin', 'src/libsndfile.def', 'src/cygsndfile.def' ]
))

View File

@@ -0,0 +1,579 @@
dnl By default, many hosts won't let programs access large files;
dnl one must use special compiler options to get large-file access to work.
dnl For more details about this brain damage please see:
dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
dnl Written by Paul Eggert <eggert@twinsun.com>.
dnl Internal subroutine of AC_SYS_EXTRA_LARGEFILE.
dnl AC_SYS_EXTRA_LARGEFILE_FLAGS(FLAGSNAME)
AC_DEFUN([AC_SYS_EXTRA_LARGEFILE_FLAGS],
[AC_CACHE_CHECK([for $1 value to request large file support],
ac_cv_sys_largefile_$1,
[ac_cv_sys_largefile_$1=`($GETCONF LFS_$1) 2>/dev/null` || {
ac_cv_sys_largefile_$1=no
ifelse($1, CFLAGS,
[case "$host_os" in
# IRIX 6.2 and later require cc -n32.
changequote(, )dnl
irix6.[2-9]* | irix6.1[0-9]* | irix[7-9].* | irix[1-9][0-9]*)
changequote([, ])dnl
if test "$GCC" != yes; then
ac_cv_sys_largefile_CFLAGS=-n32
fi
ac_save_CC="$CC"
CC="$CC $ac_cv_sys_largefile_CFLAGS"
AC_TRY_LINK(, , , ac_cv_sys_largefile_CFLAGS=no)
CC="$ac_save_CC"
esac])
}])])
dnl Internal subroutine of AC_SYS_EXTRA_LARGEFILE.
dnl AC_SYS_EXTRA_LARGEFILE_SPACE_APPEND(VAR, VAL)
AC_DEFUN([AC_SYS_EXTRA_LARGEFILE_SPACE_APPEND],
[case $2 in
no) ;;
?*)
case "[$]$1" in
'') $1=$2 ;;
*) $1=[$]$1' '$2 ;;
esac ;;
esac])
dnl Internal subroutine of AC_SYS_EXTRA_LARGEFILE.
dnl AC_SYS_EXTRA_LARGEFILE_MACRO_VALUE(C-MACRO, CACHE-VAR, COMMENT, CODE-TO-SET-DEFAULT)
AC_DEFUN([AC_SYS_EXTRA_LARGEFILE_MACRO_VALUE],
[AC_CACHE_CHECK([for $1], $2,
[$2=no
changequote(, )dnl
$4
for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
case "$ac_flag" in
-D$1)
$2=1 ;;
-D$1=*)
$2=`expr " $ac_flag" : '[^=]*=\(.*\)'` ;;
esac
done
changequote([, ])dnl
])
if test "[$]$2" != no; then
AC_DEFINE_UNQUOTED([$1], [$]$2, [$3])
fi])
AC_DEFUN([AC_SYS_EXTRA_LARGEFILE],
[AC_REQUIRE([AC_CANONICAL_HOST])
AC_ARG_ENABLE(largefile,
[ --disable-largefile omit support for large files])
if test "$enable_largefile" != no; then
AC_CHECK_TOOL(GETCONF, getconf)
AC_SYS_EXTRA_LARGEFILE_FLAGS(CFLAGS)
AC_SYS_EXTRA_LARGEFILE_FLAGS(LDFLAGS)
AC_SYS_EXTRA_LARGEFILE_FLAGS(LIBS)
for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
case "$ac_flag" in
no) ;;
-D_FILE_OFFSET_BITS=*) ;;
-D_LARGEFILE_SOURCE | -D_LARGEFILE_SOURCE=*) ;;
-D_LARGE_FILES | -D_LARGE_FILES=*) ;;
-D?* | -I?*)
AC_SYS_EXTRA_LARGEFILE_SPACE_APPEND(CPPFLAGS, "$ac_flag") ;;
*)
AC_SYS_EXTRA_LARGEFILE_SPACE_APPEND(CFLAGS, "$ac_flag") ;;
esac
done
AC_SYS_EXTRA_LARGEFILE_SPACE_APPEND(LDFLAGS, "$ac_cv_sys_largefile_LDFLAGS")
AC_SYS_EXTRA_LARGEFILE_SPACE_APPEND(LIBS, "$ac_cv_sys_largefile_LIBS")
AC_SYS_EXTRA_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS,
ac_cv_sys_file_offset_bits,
[Number of bits in a file offset, on hosts where this is settable.])
[case "$host_os" in
# HP-UX 10.20 and later
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
ac_cv_sys_file_offset_bits=64 ;;
esac]
AC_SYS_EXTRA_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE,
ac_cv_sys_largefile_source,
[Define to make fseeko etc. visible, on some hosts.],
[case "$host_os" in
# HP-UX 10.20 and later
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
ac_cv_sys_largefile_source=1 ;;
esac])
AC_SYS_EXTRA_LARGEFILE_MACRO_VALUE(_LARGE_FILES,
ac_cv_sys_large_files,
[Define for large files, on AIX-style hosts.],
[case "$host_os" in
# AIX 4.2 and later
aix4.[2-9]* | aix4.1[0-9]* | aix[5-9].* | aix[1-9][0-9]*)
ac_cv_sys_large_files=1 ;;
esac])
fi
])
dnl @synopsis AC_C_FIND_ENDIAN
dnl
dnl Determine endian-ness of target processor.
dnl @version 1.1 Mar 03 2002
dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
dnl
dnl Majority written from scratch to replace the standard autoconf macro
dnl AC_C_BIGENDIAN. Only part remaining from the original it the invocation
dnl of the AC_TRY_RUN macro.
dnl
dnl Permission to use, copy, modify, distribute, and sell this file for any
dnl purpose is hereby granted without fee, provided that the above copyright
dnl and this permission notice appear in all copies. No representations are
dnl made about the suitability of this software for any purpose. It is
dnl provided "as is" without express or implied warranty.
dnl Find endian-ness in the following way:
dnl 1) Look in <endian.h>.
dnl 2) If 1) fails, look in <sys/types.h> and <sys/param.h>.
dnl 3) If 1) and 2) fails and not cross compiling run a test program.
dnl 4) If 1) and 2) fails and cross compiling then guess based on target.
AC_DEFUN([AC_C_FIND_ENDIAN],
[AC_CACHE_CHECK(processor byte ordering,
ac_cv_c_byte_order,
# Initialize to unknown
ac_cv_c_byte_order=unknown
if test x$ac_cv_header_endian_h = xyes ; then
# First try <endian.h> which should set BYTE_ORDER.
[AC_TRY_LINK([
#include <endian.h>
#if BYTE_ORDER != LITTLE_ENDIAN
not big endian
#endif
], return 0 ;,
ac_cv_c_byte_order=little
)]
[AC_TRY_LINK([
#include <endian.h>
#if BYTE_ORDER != BIG_ENDIAN
not big endian
#endif
], return 0 ;,
ac_cv_c_byte_order=big
)]
fi
if test $ac_cv_c_byte_order = unknown ; then
[AC_TRY_LINK([
#include <sys/types.h>
#include <sys/param.h>
#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
bogus endian macros
#endif
], return 0 ;,
[AC_TRY_LINK([
#include <sys/types.h>
#include <sys/param.h>
#if BYTE_ORDER != LITTLE_ENDIAN
not big endian
#endif
], return 0 ;,
ac_cv_c_byte_order=little
)]
[AC_TRY_LINK([
#include <sys/types.h>
#include <sys/param.h>
#if BYTE_ORDER != LITTLE_ENDIAN
not big endian
#endif
], return 0 ;,
ac_cv_c_byte_order=little
)]
)]
fi
if test $ac_cv_c_byte_order = unknown ; then
if test $cross_compiling = yes ; then
# This is the last resort. Try to guess the target processor endian-ness
# by looking at the target CPU type.
[
case "$target_cpu" in
alpha* | i?86* | mipsel* | ia64*)
ac_cv_c_big_endian=0
ac_cv_c_little_endian=1
;;
m68* | mips* | powerpc* | hppa* | sparc*)
ac_cv_c_big_endian=1
ac_cv_c_little_endian=0
;;
esac
]
else
AC_TRY_RUN(
[[
int main (void)
{ /* Are we little or big endian? From Harbison&Steele. */
union
{ long l ;
char c [sizeof (long)] ;
} u ;
u.l = 1 ;
return (u.c [sizeof (long) - 1] == 1);
}
]], , ac_cv_c_byte_order=big,
ac_cv_c_byte_order=unknown
)
AC_TRY_RUN(
[[int main (void)
{ /* Are we little or big endian? From Harbison&Steele. */
union
{ long l ;
char c [sizeof (long)] ;
} u ;
u.l = 1 ;
return (u.c [0] == 1);
}]], , ac_cv_c_byte_order=little,
ac_cv_c_byte_order=unknown
)
fi
fi
)
]
if test $ac_cv_c_byte_order = big ; then
ac_cv_c_big_endian=1
ac_cv_c_little_endian=0
elif test $ac_cv_c_byte_order = little ; then
ac_cv_c_big_endian=0
ac_cv_c_little_endian=1
else
ac_cv_c_big_endian=0
ac_cv_c_little_endian=0
AC_MSG_WARN([[*****************************************************************]])
AC_MSG_WARN([[*** Not able to determine endian-ness of target processor. ]])
AC_MSG_WARN([[*** The constants CPU_IS_BIG_ENDIAN and CPU_IS_LITTLE_ENDIAN in ]])
AC_MSG_WARN([[*** src/config.h may need to be hand editied. ]])
AC_MSG_WARN([[*****************************************************************]])
fi
)# AC_C_FIND_ENDIAN
dnl @synopsis AC_C99_FLEXIBLE_ARRAY
dnl
dnl Dose the compiler support the 1999 ISO C Standard "stuct hack".
dnl @version 1.1 Mar 15 2004
dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
dnl
dnl Permission to use, copy, modify, distribute, and sell this file for any
dnl purpose is hereby granted without fee, provided that the above copyright
dnl and this permission notice appear in all copies. No representations are
dnl made about the suitability of this software for any purpose. It is
dnl provided "as is" without express or implied warranty.
AC_DEFUN([AC_C99_FLEXIBLE_ARRAY],
[AC_CACHE_CHECK(C99 struct flexible array support,
ac_cv_c99_flexible_array,
# Initialize to unknown
ac_cv_c99_flexible_array=no
AC_TRY_LINK([[
#include <stdlib.h>
typedef struct {
int k;
char buffer [] ;
} MY_STRUCT ;
]],
[ MY_STRUCT *p = calloc (1, sizeof (MY_STRUCT) + 42); ],
ac_cv_c99_flexible_array=yes,
ac_cv_c99_flexible_array=no
))]
) # AC_C99_FLEXIBLE_ARRAY
dnl @synopsis AC_C99_FUNC_LRINT
dnl
dnl Check whether C99's lrint function is available.
dnl @version 1.3 Feb 12 2002
dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
dnl
dnl Permission to use, copy, modify, distribute, and sell this file for any
dnl purpose is hereby granted without fee, provided that the above copyright
dnl and this permission notice appear in all copies. No representations are
dnl made about the suitability of this software for any purpose. It is
dnl provided "as is" without express or implied warranty.
dnl
AC_DEFUN([AC_C99_FUNC_LRINT],
[AC_CACHE_CHECK(for lrint,
ac_cv_c99_lrint,
[
lrint_save_CFLAGS=$CFLAGS
CFLAGS="-O2 -lm"
AC_TRY_LINK([
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC99 1
#define __USE_ISOC9X 1
#include <math.h>
], if (!lrint(3.14159)) lrint(2.7183);, ac_cv_c99_lrint=yes, ac_cv_c99_lrint=no)
CFLAGS=$lrint_save_CFLAGS
])
if test "$ac_cv_c99_lrint" = yes; then
AC_DEFINE(HAVE_LRINT, 1,
[Define if you have C99's lrint function.])
fi
])# AC_C99_FUNC_LRINT
dnl @synopsis AC_C99_FUNC_LRINTF
dnl
dnl Check whether C99's lrintf function is available.
dnl @version 1.3 Feb 12 2002
dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
dnl
dnl Permission to use, copy, modify, distribute, and sell this file for any
dnl purpose is hereby granted without fee, provided that the above copyright
dnl and this permission notice appear in all copies. No representations are
dnl made about the suitability of this software for any purpose. It is
dnl provided "as is" without express or implied warranty.
dnl
AC_DEFUN([AC_C99_FUNC_LRINTF],
[AC_CACHE_CHECK(for lrintf,
ac_cv_c99_lrintf,
[
lrintf_save_CFLAGS=$CFLAGS
CFLAGS="-O2 -lm"
AC_TRY_LINK([
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC99 1
#define __USE_ISOC9X 1
#include <math.h>
], if (!lrintf(3.14159)) lrintf(2.7183);, ac_cv_c99_lrintf=yes, ac_cv_c99_lrintf=no)
CFLAGS=$lrintf_save_CFLAGS
])
if test "$ac_cv_c99_lrintf" = yes; then
AC_DEFINE(HAVE_LRINTF, 1,
[Define if you have C99's lrintf function.])
fi
])# AC_C99_FUNC_LRINTF
dnl @synopsis AC_C99_FUNC_LLRINT
dnl
dnl Check whether C99's llrint function is available.
dnl @version 1.1 Sep 30 2002
dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
dnl
dnl Permission to use, copy, modify, distribute, and sell this file for any
dnl purpose is hereby granted without fee, provided that the above copyright
dnl and this permission notice appear in all copies. No representations are
dnl made about the suitability of this software for any purpose. It is
dnl provided "as is" without express or implied warranty.
dnl
AC_DEFUN([AC_C99_FUNC_LLRINT],
[AC_CACHE_CHECK(for llrint,
ac_cv_c99_llrint,
[
llrint_save_CFLAGS=$CFLAGS
CFLAGS="-O2 -lm"
AC_TRY_LINK([
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC99 1
#define __USE_ISOC9X 1
#include <math.h>
#include <stdint.h>
], int64_t x ; x = llrint(3.14159) ;, ac_cv_c99_llrint=yes, ac_cv_c99_llrint=no)
CFLAGS=$llrint_save_CFLAGS
])
if test "$ac_cv_c99_llrint" = yes; then
AC_DEFINE(HAVE_LLRINT, 1,
[Define if you have C99's llrint function.])
fi
])# AC_C99_FUNC_LLRINT
dnl @synopsis AC_C_CLIP_MODE
dnl
dnl Determine the clipping mode when converting float to int.
dnl @version 1.0 May 17 2003
dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com>
dnl
dnl Permission to use, copy, modify, distribute, and sell this file for any
dnl purpose is hereby granted without fee, provided that the above copyright
dnl and this permission notice appear in all copies. No representations are
dnl made about the suitability of this software for any purpose. It is
dnl provided "as is" without express or implied warranty.
dnl Find the clipping mode in the following way:
dnl 1) If we are not cross compiling test it.
dnl 2) IF we are cross compiling, assume that clipping isn't done correctly.
AC_DEFUN([AC_C_CLIP_MODE],
[AC_CACHE_CHECK(processor clipping capabilities,
ac_cv_c_clip_type,
# Initialize to unknown
ac_cv_c_clip_positive=unknown
ac_cv_c_clip_negative=unknown
if test $ac_cv_c_clip_positive = unknown ; then
AC_TRY_RUN(
[[
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC99 1
#define __USE_ISOC9X 1
#include <math.h>
int main (void)
{ double fval ;
int k, ival ;
fval = 1.0 * 0x7FFFFFFF ;
for (k = 0 ; k < 100 ; k++)
{ ival = (lrint (fval)) >> 24 ;
if (ival != 127)
return 1 ;
fval *= 1.2499999 ;
} ;
return 0 ;
}
]],
ac_cv_c_clip_positive=yes,
ac_cv_c_clip_positive=no,
ac_cv_c_clip_positive=unknown
)
AC_TRY_RUN(
[[
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC99 1
#define __USE_ISOC9X 1
#include <math.h>
int main (void)
{ double fval ;
int k, ival ;
fval = -8.0 * 0x10000000 ;
for (k = 0 ; k < 100 ; k++)
{ ival = (lrint (fval)) >> 24 ;
if (ival != -128)
return 1 ;
fval *= 1.2499999 ;
} ;
return 0 ;
}
]],
ac_cv_c_clip_negative=yes,
ac_cv_c_clip_negative=no,
ac_cv_c_clip_negative=unknown
)
fi
if test $ac_cv_c_clip_positive = yes ; then
ac_cv_c_clip_positive=1
else
ac_cv_c_clip_positive=0
fi
if test $ac_cv_c_clip_negative = yes ; then
ac_cv_c_clip_negative=1
else
ac_cv_c_clip_negative=0
fi
[[
case "$ac_cv_c_clip_positive$ac_cv_c_clip_negative" in
"00")
ac_cv_c_clip_type="none"
;;
"10")
ac_cv_c_clip_type="positive"
;;
"01")
ac_cv_c_clip_type="negative"
;;
"11")
ac_cv_c_clip_type="both"
;;
esac
]]
)
]
)# AC_C_CLIP_MODE
dnl @synopsis AC_ADD_CFLAGS
dnl
dnl Add the given option to CFLAGS, if it doesn't break the compiler
AC_DEFUN([AC_ADD_CFLAGS],
[AC_MSG_CHECKING([if $CC accepts $1])
ac_add_cflags__old_cflags="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_TRY_LINK([#include <stdio.h>],
[printf("Hello, World!\n"); return 0;],
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
CFLAGS="$ac_add_cflags__old_cflags")
])
ifelse(dnl
Do not edit or modify anything in this comment block.
The arch-tag line is a file identity tag for the GNU Arch
revision control system.
arch-tag: bc38294d-bb5c-42ad-90b9-779def5eaab7
)dnl

72
libs/libsndfile/aclocal.m4 vendored Normal file
View File

@@ -0,0 +1,72 @@
# generated automatically by aclocal 1.9.2 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
dnl also defines GSTUFF_PKG_ERRORS on error
AC_DEFUN([PKG_CHECK_MODULES], [
succeeded=no
if test -z "$PKG_CONFIG"; then
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
fi
if test "$PKG_CONFIG" = "no" ; then
echo "*** The pkg-config script could not be found. Make sure it is"
echo "*** in your path, or set the PKG_CONFIG environment variable"
echo "*** to the full path to pkg-config."
echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
else
PKG_CONFIG_MIN_VERSION=0.9.0
if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
AC_MSG_CHECKING(for $2)
if $PKG_CONFIG --exists "$2" ; then
AC_MSG_RESULT(yes)
succeeded=yes
AC_MSG_CHECKING($1_CFLAGS)
$1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
AC_MSG_RESULT($$1_CFLAGS)
AC_MSG_CHECKING($1_LIBS)
$1_LIBS=`$PKG_CONFIG --libs "$2"`
AC_MSG_RESULT($$1_LIBS)
else
$1_CFLAGS=""
$1_LIBS=""
## If we have a custom action on failure, don't print errors, but
## do set a variable so people can do so.
$1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
ifelse([$4], ,echo $$1_PKG_ERRORS,)
fi
AC_SUBST($1_CFLAGS)
AC_SUBST($1_LIBS)
else
echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
echo "*** See http://www.freedesktop.org/software/pkgconfig"
fi
fi
if test $succeeded = yes; then
ifelse([$3], , :, [$3])
else
ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
fi
])
m4_include([acinclude.m4])

107
libs/libsndfile/compile Executable file
View File

@@ -0,0 +1,107 @@
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
# Copyright 1999, 2000 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.
# Usage:
# compile PROGRAM [ARGS]...
# `-o FOO.o' is removed from the args passed to the actual compile.
# Usage statement added by Billy Biggs <vektor@dumbterm.net>.
if [ -z $1 ]; then
echo "Wrapper for compilers which do not understand '-c -o'."
echo "usage: compile PROGRAM [ARGS]..."
echo "'-o FOO.o' is removed from the args passed to the actual compile."
exit 1
fi
prog=$1
shift
ofile=
cfile=
args=
while test $# -gt 0; do
case "$1" in
-o)
# configure might choose to run compile as `compile cc -o foo foo.c'.
# So we do something ugly here.
ofile=$2
shift
case "$ofile" in
*.o | *.obj)
;;
*)
args="$args -o $ofile"
ofile=
;;
esac
;;
*.c)
cfile=$1
args="$args $1"
;;
*)
args="$args $1"
;;
esac
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no `-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# `.c' file was seen then we are probably linking. That is also
# ok.
exec "$prog" $args
fi
# Name of file we expect compiler to create.
cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
# Create the lock directory.
# Note: use `[/.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d
while true; do
if mkdir $lockdir > /dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir $lockdir; exit 1" 1 2 15
# Run the compile.
"$prog" $args
status=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
fi
rmdir $lockdir
exit $status

1497
libs/libsndfile/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1608
libs/libsndfile/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

13925
libs/libsndfile/configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,541 @@
# Copyright (C) 1999-2006 Erik de Castro Lopo (erikd AT mega-nerd DOT com).
dnl Require autoconf version
AC_PREREQ(2.59)
AC_INIT([libsndfile],[ardour-special],[ardour@ardour.org])
AC_CONFIG_SRCDIR([src/sndfile.c])
AC_CANONICAL_TARGET([])
AC_CONFIG_HEADERS(src/config.h)
AC_LANG([C])
#------------------------------------------------------------------------------------
# Rules for library version information:
#
# 1. Start with version information of `0:0:0' for each libtool library.
# 2. Update the version information only immediately before a public release of
# your software. More frequent updates are unnecessary, and only guarantee
# that the current interface number gets larger faster.
# 3. If the library source code has changed at all since the last update, then
# increment revision (`c:r:a' becomes `c:r+1:a').
# 4. If any interfaces have been added, removed, or changed since the last update,
# increment current, and set revision to 0.
# 5. If any interfaces have been added since the last public release, then increment
# age.
# 6. If any interfaces have been removed since the last public release, then set age
# to 0.
SHARED_VERSION_INFO="1:16:0"
AC_PROG_CC
#AM_PROG_LIBTOOL
AC_CHECK_PROG(autogen, autogen, yes, no)
AC_PROG_INSTALL
AC_PROG_LN_S
AC_HEADER_STDC
AC_CHECK_HEADERS(endian.h)
AC_CHECK_HEADERS(byteswap.h)
AC_CHECK_HEADERS(locale.h)
AC_CHECK_HEADERS(inttypes.h)
AC_HEADER_SYS_WAIT
AC_CHECK_DECLS(S_IRGRP)
AC_DEFINE_UNQUOTED([HAVE_DECL_S_IRGRP],${HAVE_DECL_S_IRGRP},
[Set to 1 if S_IRGRP is defined.])
#====================================================================================
# Check for support of the struct hack.
AC_C99_FLEXIBLE_ARRAY
if test x$ac_cv_c99_flexible_array = xyes ; then
AC_DEFINE([HAVE_FLEXIBLE_ARRAY],1, [Set to 1 if the compile supports the struct hack.])
else
AC_MSG_WARN([[*** This compiler does not support the 1999 ISO C Standard ***]])
AC_MSG_WARN([[*** feature known as the flexible array struct member. ***]])
AC_DEFINE([HAVE_FLEXIBLE_ARRAY],0)
fi
#====================================================================================
# Couple of initializations here. Fill in real values later.
SHLIB_VERSION_ARG=""
#====================================================================================
# Finished checking, handle options.
AC_ARG_ENABLE(experimental,
AC_HELP_STRING([--enable-experimental], [enable experimental code]))
EXPERIMENTAL_CODE=0
if test x$enable_experimental = xyes ; then
EXPERIMENTAL_CODE=1
fi
AC_DEFINE_UNQUOTED([ENABLE_EXPERIMENTAL_CODE],${EXPERIMENTAL_CODE}, [Set to 1 to enable experimental code.])
AC_ARG_ENABLE(gcc-werror,
AC_HELP_STRING([--enable-gcc-werror], [enable -Werror in all Makefiles]))
AC_ARG_ENABLE(gcc-pipe,
AC_HELP_STRING([--disable-gcc-pipe], [disable gcc -pipe option]))
AC_ARG_ENABLE(gcc-opt,
AC_HELP_STRING([--disable-gcc-opt], [disable gcc optimisations]))
AC_ARG_ENABLE(cpu-clip,
AC_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper]))
AC_ARG_ENABLE(bow-docs,
AC_HELP_STRING([--enable-bow-docs], [enable black-on-white html docs]))
AC_ARG_ENABLE(sqlite,
AC_HELP_STRING([--disable-sqlite], [disable use of sqlite]))
AC_ARG_ENABLE(flac,
AC_HELP_STRING([--disable-flac], [disable use of FLAC]))
AC_ARG_ENABLE(alsa,
AC_HELP_STRING([--disable-alsa], [disable use of ALSA]))
#====================================================================================
# Check types and their sizes.
AC_CHECK_SIZEOF(short,2)
AC_CHECK_SIZEOF(int,4)
AC_CHECK_SIZEOF(long,4)
AC_CHECK_SIZEOF(float,4)
AC_CHECK_SIZEOF(double,4)
AC_CHECK_SIZEOF(void*,8)
AC_CHECK_SIZEOF(size_t,4)
AC_CHECK_SIZEOF(int64_t,8)
AC_CHECK_SIZEOF(long long,8)
#====================================================================================
# Find an appropriate type for sf_count_t.
# On systems supporting files larger than 2 Gig, sf_count_t must be a 64 bit value.
# Unfortunately there is more than one way of ensuring this so need to do some
# pretty rigourous testing here.
unset ac_cv_sizeof_off_t
AC_CHECK_SIZEOF(off_t,1) # Fake default value.
case "$host_os" in
mingw*)
TYPEOF_SF_COUNT_T="__int64"
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
SIZEOF_SF_COUNT_T=8
;;
*)
if test "x$ac_cv_sizeof_off_t" = "x8" ; then
# If sizeof (off_t) is 8, no further checking is needed.
TYPEOF_SF_COUNT_T="off_t"
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
SIZEOF_SF_COUNT_T=8
else
# Check for common 64 bit file offset types.
AC_CHECK_SIZEOF(loff_t,1) # Fake default value.
AC_CHECK_SIZEOF(off64_t,1) # Fake default value.
TYPEOF_SF_COUNT_T="unknown"
if test "x$ac_cv_sizeof_loff_t" = "x8" ; then
TYPEOF_SF_COUNT_T="loff_t"
SIZEOF_SF_COUNT_T=8
elif test "x$ac_cv_sizeof_off64_t" = "x8" ; then
TYPEOF_SF_COUNT_T="off64_t"
SIZEOF_SF_COUNT_T=8
fi
# Save the old sizeof (off_t) value and then unset it to see if it
# changes when Large File Support is enabled.
pre_largefile_sizeof_off_t=$ac_cv_sizeof_off_t
unset ac_cv_sizeof_off_t
AC_SYS_EXTRA_LARGEFILE
if test "x$ac_cv_sys_largefile_CFLAGS" = "xno" ; then
ac_cv_sys_largefile_CFLAGS=""
fi
if test "x$ac_cv_sys_largefile_LDFLAGS" = "xno" ; then
ac_cv_sys_largefile_LDFLAGS=""
fi
if test "x$ac_cv_sys_largefile_LIBS" = "xno" ; then
ac_cv_sys_largefile_LIBS=""
fi
AC_CHECK_SIZEOF(off_t,1) # Fake default value.
if test "x$ac_cv_sizeof_off_t" = "x8" ; then
SF_COUNT_MAX="0x7FFFFFFFFFFFFFFFLL"
elif test "x$ac_cv_sizeof_off_t" = "x$pre_largefile_sizeof_off_t" ; then
AC_MSG_WARN([[This machine does not seem to support 64 bit file offsets.]])
TYPEOF_SF_COUNT_T="off_t"
SIZEOF_SF_COUNT_T=$ac_cv_sizeof_off_t
elif test "x$TYPEOF_SF_COUNT_T" = "xunknown" ; then
echo
echo "*** The configure process has determined that this system is capable"
echo "*** of Large File Support but has not been able to find a type which"
echo "*** is an unambiguous 64 bit file offset."
echo "*** Please contact the author to help resolve this problem."
echo
AC_MSG_ERROR([[Bad file offset type.]])
fi
fi
;;
esac
if test $SIZEOF_SF_COUNT_T = 4 ; then
SF_COUNT_MAX="0x7FFFFFFF"
fi
AC_DEFINE_UNQUOTED([TYPEOF_SF_COUNT_T],${TYPEOF_SF_COUNT_T}, [Set to long if unknown.])
AC_SUBST(TYPEOF_SF_COUNT_T)
AC_DEFINE_UNQUOTED([SIZEOF_SF_COUNT_T],${SIZEOF_SF_COUNT_T}, [Set to sizeof (long) if unknown.])
AC_SUBST(SIZEOF_SF_COUNT_T)
AC_DEFINE_UNQUOTED([SF_COUNT_MAX],${SF_COUNT_MAX}, [Set to maximum allowed value of sf_count_t type.])
AC_SUBST(SF_COUNT_MAX)
AC_CHECK_TYPES(ssize_t)
AC_CHECK_SIZEOF(ssize_t,4)
#====================================================================================
# Determine endian-ness of target processor.
AC_C_FIND_ENDIAN
AC_DEFINE_UNQUOTED(CPU_IS_BIG_ENDIAN, ${ac_cv_c_big_endian},
[Target processor is big endian.])
AC_DEFINE_UNQUOTED(CPU_IS_LITTLE_ENDIAN, ${ac_cv_c_little_endian},
[Target processor is little endian.])
#====================================================================================
# Check for functions.
AC_CHECK_FUNCS(malloc calloc realloc free)
AC_CHECK_FUNCS(open read write lseek pread pwrite)
AC_CHECK_FUNCS(fstat ftruncate fsync fdatasync)
AC_CHECK_FUNCS(snprintf vsnprintf)
AC_CHECK_FUNCS(gmtime gmtime_r)
AC_CHECK_FUNCS(mmap getpagesize)
AC_CHECK_FUNCS(setlocale)
AC_CHECK_LIB([m],floor)
AC_CHECK_FUNCS(floor ceil fmod)
case "$host_os" in
cygwin*)
AC_MSG_WARN([[Not using built-in lrint() and lrintf() because they are broken on Cygwin.]])
;;
*)
AC_C99_FUNC_LRINT
AC_C99_FUNC_LRINTF
if test "x$ac_cv_c99_lrint" = "xno" ; then
if test "x$ac_cv_c99_lrintf" = "xno" ; then
AC_MSG_WARN([[*** Missing C99 standard functions lrint() and lrintf().]])
AC_MSG_WARN([[*** This may cause benign compiler warnings on some systems (ie Solaris).]])
fi
fi
;;
esac
#====================================================================================
# Check for libsqlite3 (only used in regtest).
ac_cv_sqlite3=no
if test x$enable_sqlite != xno ; then
PKG_CHECK_MODULES(SQLITE3, sqlite3 >= 3.2, ac_cv_sqlite3=yes, ac_cv_sqlite3=no)
fi
if test x$ac_cv_sqlite3 = "xyes" ; then
HAVE_SQLITE3=1
else
HAVE_SQLITE3=0
fi
AC_DEFINE_UNQUOTED([HAVE_SQLITE3],$HAVE_SQLITE3,[Set to 1 if you have libsqlite3.])
#====================================================================================
# Determine if the processor can do clipping on float to int conversions.
if test x$enable_cpu_clip != "xno" ; then
AC_C_CLIP_MODE
else
echo "checking processor clipping capabilities... disabled"
ac_cv_c_clip_positive=0
ac_cv_c_clip_negative=0
fi
AC_DEFINE_UNQUOTED(CPU_CLIPS_POSITIVE, ${ac_cv_c_clip_positive},
[Target processor clips on positive float to int conversion.])
AC_DEFINE_UNQUOTED(CPU_CLIPS_NEGATIVE, ${ac_cv_c_clip_negative},
[Target processor clips on negative float to int conversion.])
#====================================================================================
# Target OS specific stuff.
OS_SPECIFIC_CFLAGS=""
OS_SPECIFIC_LINKS=""
os_is_win32=0
os_is_macosx=0
use_windows_api=0
case "$host_os" in
darwin* | rhapsody*)
os_is_macosx=1
OS_SPECIFIC_CFLAGS="-fpascal-strings -I/Developer/Headers/FlatCarbon"
OS_SPECIFIC_LINKS="-framework CoreAudio"
;;
mingw*)
os_is_win32=1
use_windows_api=1
OS_SPECIFIC_LINKS="-lwinmm"
;;
cygwin*)
os_is_win32=1
OS_SPECIFIC_LINKS="-lwinmm"
;;
esac
AC_DEFINE_UNQUOTED(OS_IS_WIN32, ${os_is_win32}, [Set to 1 if compiling for Win32])
AC_DEFINE_UNQUOTED(OS_IS_MACOSX, ${os_is_macosx}, [Set to 1 if compiling for MacOSX])
AC_DEFINE_UNQUOTED(USE_WINDOWS_API, ${use_windows_api}, [Set to 1 to use the native windows API])
#====================================================================================
# Check for ALSA.
ALSA_LIBS=""
if test x$enable_alsa != xno ; then
AC_CHECK_HEADERS(alsa/asoundlib.h)
if test x$ac_cv_header_alsa_asoundlib_h = xyes ; then
ALSA_LIBS="-lasound"
fi
fi
#====================================================================================
# Check for FLAC
FLAC_LIBS=""
if test x$enable_flac != xno ; then
AC_CHECK_HEADERS(FLAC/all.h)
if test x$ac_cv_header_FLAC_all_h = xyes ; then
AC_CHECK_LIB(FLAC, FLAC__seekable_stream_encoder_set_tell_callback, HAVE_FLAC_1_1_1="yes")
if test "x$HAVE_FLAC_1_1_1" = xyes ; then
AC_DEFINE(HAVE_FLAC_1_1_1, [1], [Define to 1 if you have libflac 1.1.1])
fi
FLAC_LIBS="-lFLAC"
fi
fi
#====================================================================================
# Test for sanity when cross-compiling.
if test x$cross_compiling = xyes ; then
AC_MSG_WARN([[******************************************************************]])
AC_MSG_WARN([[*** We are cross-compiling, so have to assume sizeof (short) == 2 ]])
AC_MSG_WARN([[*** and sizeof (int) == 4. If this is not the case there is no ]])
AC_MSG_WARN([[*** chance of this working. Please contact the mantainer. ]])
AC_MSG_WARN([[******************************************************************]])
fi
if test $ac_cv_sizeof_short != 2 ; then
AC_MSG_WARN([[******************************************************************]])
AC_MSG_WARN([[*** sizeof (short) != 2. ]])
AC_MSG_WARN([[******************************************************************]])
fi
if test $ac_cv_sizeof_int != 4 ; then
AC_MSG_WARN([[******************************************************************]])
AC_MSG_WARN([[*** sizeof (int) != 4 ]])
AC_MSG_WARN([[******************************************************************]])
fi
if test $ac_cv_sizeof_float != 4 ; then
AC_MSG_WARN([[******************************************************************]])
AC_MSG_WARN([[*** sizeof (float) != 4. ]])
AC_MSG_WARN([[******************************************************************]])
fi
if test $ac_cv_sizeof_double != 8 ; then
AC_MSG_WARN([[******************************************************************]])
AC_MSG_WARN([[*** sizeof (double) != 8. ]])
AC_MSG_WARN([[******************************************************************]])
fi
if test x"$ac_cv_prog_autogen" = "xno" ; then
AC_MSG_WARN([[Touching files in directory tests/.]])
touch tests/*.c tests/*.h
fi
#====================================================================================
# Settings for the HTML documentation.
htmldocdir=$prefix/share/doc/libsndfile1-dev/html
if test $prefix = "NONE" ; then
htmldocdir=/usr/local/share/doc/libsndfile1-dev/html
else
htmldocdir=$prefix/share/doc/libsndfile1-dev/html
fi
if test x$enable_bow_docs = "xyes" ; then
HTML_BGCOLOUR="white"
HTML_FGCOLOUR="black"
else
HTML_BGCOLOUR="black"
HTML_FGCOLOUR="white"
fi
#====================================================================================
# Now use the information from the checking stage.
if test x$ac_cv_c_compiler_gnu = xyes ; then
AC_ADD_CFLAGS(-std=gnu99)
CFLAGS="$CFLAGS -W -Wall"
AC_ADD_CFLAGS(-Wdeclaration-after-statement)
if test x$enable_gcc_werror = "xyes" ; then
CFLAGS="-Werror $CFLAGS"
fi
CFLAGS="$CFLAGS -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wbad-function-cast -Wwrite-strings"
# -Wpointer-arith -Wundef -Wmissing-declarations -Winline -Wconversion"
if test "x$enable_gcc_opt" = "xno" ; then
temp_CFLAGS=`echo $CFLAGS | sed "s/O2/O0/"`
CFLAGS=$temp_CFLAGS
AC_MSG_WARN([[*** Compiler optimisations switched off. ***]])
fi
# OS specific tweaks.
case "$host_os" in
darwin* | rhapsody*)
# Disable -Wall, -pedantic and -Wshadow for Apple Darwin/Rhapsody.
# System headers on these systems are broken.
temp_CFLAGS=`echo $CFLAGS | sed "s/-Wall -pedantic//" | sed "s/-Wshadow//" | sed "s/-Waggregate-return//"`
CFLAGS=$temp_CFLAGS
SHLIB_VERSION_ARG="-Wl,-exported_symbols_list -Wl,\$(srcdir)/Symbols.darwin"
;;
linux*)
SHLIB_VERSION_ARG="-Wl,--version-script=\$(srcdir)/Symbols.linux"
;;
mingw*)
SHLIB_VERSION_ARG="-Wl,\$(srcdir)/libsndfile.def"
;;
cygwin*)
SHLIB_VERSION_ARG="-Wl,\$(srcdir)/cygsndfile.def"
;;
*)
;;
esac
if test x$enable_gcc_pipe != "xno" ; then
CFLAGS="$CFLAGS -pipe"
fi
AC_DEFINE([COMPILER_IS_GCC],1, [Set to 1 if the compile is GNU GCC.])
GCC_MAJOR_VERSION=`$CC -dumpversion | sed "s/\..*//"`
AC_DEFINE_UNQUOTED([GCC_MAJOR_VERSION],${GCC_MAJOR_VERSION}, [Major version of GCC or 3 otherwise.])
fi
CFLAGS="$CFLAGS $OS_SPECIFIC_CFLAGS"
if test x"$CFLAGS" = x ; then
echo "Error in configure script. CFLAGS has been screwed up."
exit
fi
AC_SUBST(htmldocdir)
AC_SUBST(HTML_BGCOLOUR)
AC_SUBST(HTML_FGCOLOUR)
AC_SUBST(SHLIB_VERSION_ARG)
AC_SUBST(SHARED_VERSION_INFO)
AC_SUBST(OS_SPECIFIC_CFLAGS)
AC_SUBST(OS_SPECIFIC_LINKS)
AC_SUBST(ALSA_LIBS)
AC_SUBST(FLAC_LIBS)
AC_SUBST(ENABLE_EXPERIMENTAL_CODE)
AC_SUBST(COMPILER_IS_GCC)
AC_SUBST(GCC_MAJOR_VERSION)
dnl The following line causes the libtool distributed with the source
dnl to be replaced if the build system has a more recent version.
AC_SUBST(LIBTOOL_DEPS)
AC_CONFIG_FILES([ \
src/sndfile.h
sndfile.pc \
])
AC_OUTPUT
#====================================================================================
AC_MSG_RESULT([
-=-=-=-=-=-=-=-=-=-= Configuration Complete =-=-=-=-=-=-=-=-=-=-
Configuration summary :
Version : ..................... ${VERSION}
Experimental code : ........... ${enable_experimental:-no}
])
if test x$ac_cv_c_compiler_gnu = xyes ; then
echo -e " Tools :\n"
echo " Compiler is GCC : ............. ${ac_cv_c_compiler_gnu}"
echo " GCC major version : ........... ${GCC_MAJOR_VERSION}"
if test $GCC_MAJOR_VERSION -lt 3 ; then
echo -e "\n ** This compiler version allows applications to write"
echo " ** to static strings within the library."
echo " ** Compile with GCC version 3.X to avoid this problem."
fi
fi
if test $libdir = "\${exec_prefix}/lib" ; then
libdir="$prefix/lib"
fi
if test $bindir = "\${exec_prefix}/bin" ; then
bindir="$prefix/bin"
fi
AC_MSG_RESULT([[
Installation directories :
Library directory : ........... $libdir
Program directory : ........... $bindir
Pkgconfig directory : ......... $libdir/pkgconfig
HTML docs directory : ......... $htmldocdir
]])
if test x$prefix != "x/usr" ; then
echo "Compiling some other packages against libsndfile may require"
echo -e "the addition of \"$libdir/pkgconfig\" to the"
echo -e "PKG_CONFIG_PATH environment variable.\n"
fi
#====================================================================================
ifelse(dnl
Do not edit or modify anything in this comment block.
The arch-tag line is a file identity tag for the GNU Arch
revision control system.
arch-tag: 6391b316-6cfc-43c2-a18a-8defdc4ee359
)dnl

479
libs/libsndfile/depcomp Executable file
View File

@@ -0,0 +1,479 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
# Copyright 1999, 2000, 2003 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, 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>.
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
# `libtool' can also be set to `yes' or `no'.
if test -z "$depfile"; then
base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'`
dir=`echo "$object" | sed 's,/.*$,/,'`
if test "$dir" = "$object"; then
dir=
fi
# FIXME: should be _deps on DOS.
depfile="$dir.deps/$base"
fi
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
tmpdepfile1="$dir.libs/$base.lo.d"
tmpdepfile2="$dir.libs/$base.d"
"$@" -Wc,-MD
else
tmpdepfile1="$dir$base.o.d"
tmpdepfile2="$dir$base.d"
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
if test -f "$tmpdepfile1"; then
tmpdepfile="$tmpdepfile1"
else
tmpdepfile="$tmpdepfile2"
fi
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 '/^# [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

294
libs/libsndfile/install-sh Executable file
View File

@@ -0,0 +1,294 @@
#!/bin/sh
#
# install - install a program, script, or datafile
#
# 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}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd=$cpprog
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "$0: no input file specified" >&2
exit 1
else
:
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d "$dst" ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f "$src" ] || [ -d "$src" ]
then
:
else
echo "$0: $src does not exist" >&2
exit 1
fi
if [ x"$dst" = x ]
then
echo "$0: no destination specified" >&2
exit 1
else
:
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d "$dst" ]
then
dst=$dst/`basename "$src"`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-$defaultIFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS=$oIFS
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp=$pathcomp$1
shift
if [ ! -d "$pathcomp" ] ;
then
$mkdirprog "$pathcomp"
else
:
fi
pathcomp=$pathcomp/
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd "$dst" &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename "$dst"`
else
dstfile=`basename "$dst" $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename "$dst"`
else
:
fi
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up temp files at exit.
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
trap '(exit $?); exit' 1 2 13 15
# Move or copy the file name to the temp name
$doit $instcmd "$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 $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
# 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 [ -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
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
fi &&
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit
}

View File

@@ -0,0 +1,69 @@
%define name @PACKAGE@
%define version @VERSION@
%define release 1
Summary: A library to handle various audio file formats.
Name: %{name}
Version: %{version}
Release: %{release}
Copyright: LGPL
Group: Libraries/Sound
Source: http://www.mega-nerd.com/libsndfile/libsndfile-%{version}.tar.gz
URL: http://www.mega-nerd.com/libsndfile/
BuildRoot: /var/tmp/%{name}-%{version}
%description
libsndfile is a C library for reading and writing sound files such as
AIFF, AU and WAV files through one standard interface. It can currently
read/write 8, 16, 24 and 32-bit PCM files as well as 32-bit floating
point WAV files and a number of compressed formats.
%package devel
Summary: Libraries, includes, etc to develop libsndfile applications
Group: Libraries
%description devel
Libraries, include files, etc you can use to develop libsndfile applications.
%prep
%setup
%build
%configure
make
%install
if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi
mkdir -p $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
%clean
if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi
%files
%defattr(-,root,root)
%doc AUTHORS COPYING ChangeLog INSTALL NEWS README TODO doc
%{_libdir}/libsndfile.so.*
%{_bindir}/*
%{_mandir}/man1/*
%{_datadir}/octave/site/m/*
%{_defaultdocdir}/libsndfile1-dev/html/*
%files devel
%defattr(-,root,root)
%{_libdir}/libsndfile.a
%{_libdir}/libsndfile.la
%{_libdir}/libsndfile.so
%{_includedir}/sndfile.h
%{_libdir}/pkgconfig/sndfile.pc
%changelog
* Sun May 15 2005 Erik de Castro Lopo <erikd@mega-nerd.com>
- Add html files to the files section.
* Tue Sep 16 2003 Erik de Castro Lopo <erikd@mega-nerd.com>
- Apply corrections from Andrew Schultz.
* Mon Oct 21 2002 Erik de Castro Lopo <erikd@mega-nerd.com>
- Force installation of sndfile.pc file.
* Thu Jul 6 2000 Josh Green <jgreen@users.sourceforge.net>
- Created libsndfile.spec.in

336
libs/libsndfile/missing Executable file
View File

@@ -0,0 +1,336 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, 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
case "$1" in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case "$1" in
-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]"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing 0.4 - GNU automake"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. 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)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. 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)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. 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*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. 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)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. 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' is missing on your system. 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 missing on your system. 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)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. 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)
if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
# We have makeinfo, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. 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."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
tar)
shift
if test -n "$run"; then
echo 1>&2 "ERROR: \`tar' requires --run"
exit 1
fi
# 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 you do not seem to have it handy on your
system. 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

111
libs/libsndfile/mkinstalldirs Executable file
View File

@@ -0,0 +1,111 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
errstatus=0
dirmode=""
usage="\
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case $1 in
-h | --help | --h*) # -h for help
echo "$usage" 1>&2
exit 0
;;
-m) # -m PERM arg
shift
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
dirmode=$1
shift
;;
--) # 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
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi
;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi
;;
esac
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
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
# End:
# mkinstalldirs ends here

View File

@@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: sndfile
Description: A library for reading and writing audio files
Requires:
Version: @VERSION@
Libs: -L${libdir} -lsndfile
Cflags: -I${includedir}

View File

@@ -0,0 +1,50 @@
2001-06-05 Erik de Castro Lopo <erikd@mega-nerd.com>
* g72x.c
Added {} in function update () to prevent 'ambiguous else' warning messages.
2000-07-14 Erik de Castro Lopo <erikd@mega-nerd.com>
* g72x.c
Modified g72x_init_state () to fit in with the new structure of the code.
Implemented g72x_encode_block () and g72x_decode_block ().
2000-07-12 Erik de Castro Lopo <erikd@mega-nerd.com>
* g72x.h
Moved nearly all definitions and function prototypes from this file have been
moved to private.h.
Added an enum defining the 4 different G72x ADPCM codecs.
Added new function prototypes to define a cleaner interface to the encoder
and decoder. This new interface also allows samples to be processed in blocks
rather than on a sample by sample basis like the original code.
* private.h
Added prototypes moved from g72x.h.
Changed struct g72x_state to a typedef struct { .. } G72x_PRIVATE.
Added fields to G72x_PRIVATE required for working on blocks of samples.
2000-06-07 Erik de Castro Lopo <erikd@mega-nerd.com>
* g72x.c
Fixed all compiler warnings.
Removed functions tandem_adjust() which is not required by libsndfile.
* g721.c
Fixed all compiler warnings.
Removed functions tandem_adjust_alaw() and tandem_adjust_ulaw () which are not
required by libsndfile.
Removed second parameter to g721_encoder () which is not required.
* g72x.h
Removed in_coding and out_coding parameters from all functions. These allowed
g72x encoding/decoding to/from A-law or u-law and are not required by libsndfile.
Removed unneeded defines for A-law, u-law and linear encoding.
* g723_16.c
Removed second parameter (in_coding) for g723_16_encoder().
Removed second parameter (out_coding) for g723_16_decoder().
* private.h
New file containing prototypes and tyepdefs private to G72x code.

View File

View File

@@ -0,0 +1,94 @@
The files in this directory comprise ANSI-C language reference implementations
of the CCITT (International Telegraph and Telephone Consultative Committee)
G.711, G.721 and G.723 voice compressions. They have been tested on Sun
SPARCstations and passed 82 out of 84 test vectors published by CCITT
(Dec. 20, 1988) for G.721 and G.723. [The two remaining test vectors,
which the G.721 decoder implementation for u-law samples did not pass,
may be in error because they are identical to two other vectors for G.723_40.]
This source code is released by Sun Microsystems, Inc. to the public domain.
Please give your acknowledgement in product literature if this code is used
in your product implementation.
Sun Microsystems supports some CCITT audio formats in Solaris 2.0 system
software. However, Sun's implementations have been optimized for higher
performance on SPARCstations.
The source files for CCITT conversion routines in this directory are:
g72x.h header file for g721.c, g723_24.c and g723_40.c
g711.c CCITT G.711 u-law and A-law compression
g72x.c common denominator of G.721 and G.723 ADPCM codes
g721.c CCITT G.721 32Kbps ADPCM coder (with g72x.c)
g723_24.c CCITT G.723 24Kbps ADPCM coder (with g72x.c)
g723_40.c CCITT G.723 40Kbps ADPCM coder (with g72x.c)
Simple conversions between u-law, A-law, and 16-bit linear PCM are invoked
as follows:
unsigned char ucode, acode;
short pcm_val;
ucode = linear2ulaw(pcm_val);
ucode = alaw2ulaw(acode);
acode = linear2alaw(pcm_val);
acode = ulaw2alaw(ucode);
pcm_val = ulaw2linear(ucode);
pcm_val = alaw2linear(acode);
The other CCITT compression routines are invoked as follows:
#include "g72x.h"
struct g72x_state state;
int sample, code;
g72x_init_state(&state);
code = {g721,g723_24,g723_40}_encoder(sample, coding, &state);
sample = {g721,g723_24,g723_40}_decoder(code, coding, &state);
where
coding = AUDIO_ENCODING_ULAW for 8-bit u-law samples
AUDIO_ENCODING_ALAW for 8-bit A-law samples
AUDIO_ENCODING_LINEAR for 16-bit linear PCM samples
This directory also includes the following sample programs:
encode.c CCITT ADPCM encoder
decode.c CCITT ADPCM decoder
Makefile makefile for the sample programs
The sample programs contain examples of how to call the various compression
routines and pack/unpack the bits. The sample programs read byte streams from
stdin and write to stdout. The input/output data is raw data (no file header
or other identifying information is embedded). The sample programs are
invoked as follows:
encode [-3|4|5] [-a|u|l] <infile >outfile
decode [-3|4|5] [-a|u|l] <infile >outfile
where:
-3 encode to (decode from) G.723 24kbps (3-bit) data
-4 encode to (decode from) G.721 32kbps (4-bit) data [the default]
-5 encode to (decode from) G.723 40kbps (5-bit) data
-a encode from (decode to) A-law data
-u encode from (decode to) u-law data [the default]
-l encode from (decode to) 16-bit linear data
Examples:
# Read 16-bit linear and output G.721
encode -4 -l <pcmfile >g721file
# Read 40Kbps G.723 and output A-law
decode -5 -a <g723file >alawfile
# Compress and then decompress u-law data using 24Kbps G.723
encode -3 <ulawin | deoced -3 >ulawout

View File

@@ -0,0 +1,162 @@
/*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g721.c
*
* Description:
*
* g721_encoder(), g721_decoder()
*
* These routines comprise an implementation of the CCITT G.721 ADPCM
* coding algorithm. Essentially, this implementation is identical to
* the bit level description except for a few deviations which
* take advantage of work station attributes, such as hardware 2's
* complement arithmetic and large memory. Specifically, certain time
* consuming operations such as multiplications are replaced
* with lookup tables and software 2's complement operations are
* replaced with hardware 2's complement.
*
* The deviation from the bit level specification (lookup tables)
* preserves the bit level performance specifications.
*
* As outlined in the G.721 Recommendation, the algorithm is broken
* down into modules. Each section of code below is preceded by
* the name of the module which it is implementing.
*
*/
#include "g72x.h"
#include "g72x_priv.h"
static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400};
/*
* Maps G.721 code word to reconstructed scale factor normalized log
* magnitude values.
*/
static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425,
425, 373, 323, 273, 213, 135, 4, -2048};
/* Maps G.721 code word to log of scale factor multiplier. */
static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122,
1122, 355, 198, 112, 64, 41, 18, -12};
/*
* Maps G.721 code words to a set of values whose long and short
* term averages are computed and then compared to give an indication
* how stationary (steady state) the signal is.
*/
static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0};
/*
* g721_encoder()
*
* Encodes the input vale of linear PCM, A-law or u-law data sl and returns
* the resulting code. -1 is returned for unknown input coding value.
*/
int
g721_encoder(
int sl,
G72x_STATE *state_ptr)
{
short sezi, se, sez; /* ACCUM */
short d; /* SUBTA */
short sr; /* ADDB */
short y; /* MIX */
short dqsez; /* ADDC */
short dq, i;
/* linearize input sample to 14-bit PCM */
sl >>= 2; /* 14-bit dynamic range */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */
d = sl - se; /* estimation difference */
/* quantize the prediction difference */
y = step_size(state_ptr); /* quantizer step size */
i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */
dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */
dqsez = sr + sez - se; /* pole prediction diff. */
update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
return (i);
}
/*
* g721_decoder()
*
* Description:
*
* Decodes a 4-bit code of G.721 encoded data of i and
* returns the resulting linear PCM, A-law or u-law value.
* return -1 for unknown out_coding value.
*/
int
g721_decoder(
int i,
G72x_STATE *state_ptr)
{
short sezi, sei, sez, se; /* ACCUM */
short y; /* MIX */
short sr; /* ADDB */
short dq;
short dqsez;
i &= 0x0f; /* mask to get proper bits */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
y = step_size(state_ptr); /* dynamic quantizer step size */
dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */
dqsez = sr - se + sez; /* pole prediction diff. */
update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
/* sr was 14-bit dynamic range */
return (sr << 2);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 101b6e25-457d-490a-99ae-e2e74a26ea24
*/

View File

@@ -0,0 +1,169 @@
/*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/* 16kbps version created, used 24kbps code and changing as little as possible.
* G.726 specs are available from ITU's gopher or WWW site (http://www.itu.ch)
* If any errors are found, please contact me at mrand@tamu.edu
* -Marc Randolph
*/
/*
* g723_16.c
*
* Description:
*
* g723_16_encoder(), g723_16_decoder()
*
* These routines comprise an implementation of the CCITT G.726 16 Kbps
* ADPCM coding algorithm. Essentially, this implementation is identical to
* the bit level description except for a few deviations which take advantage
* of workstation attributes, such as hardware 2's complement arithmetic.
*
*/
#include "g72x.h"
#include "g72x_priv.h"
/*
* Maps G.723_16 code word to reconstructed scale factor normalized log
* magnitude values. Comes from Table 11/G.726
*/
static short _dqlntab[4] = { 116, 365, 365, 116};
/* Maps G.723_16 code word to log of scale factor multiplier.
*
* _witab[4] is actually {-22 , 439, 439, -22}, but FILTD wants it
* as WI << 5 (multiplied by 32), so we'll do that here
*/
static short _witab[4] = {-704, 14048, 14048, -704};
/*
* Maps G.723_16 code words to a set of values whose long and short
* term averages are computed and then compared to give an indication
* how stationary (steady state) the signal is.
*/
/* Comes from FUNCTF */
static short _fitab[4] = {0, 0xE00, 0xE00, 0};
/* Comes from quantizer decision level tables (Table 7/G.726)
*/
static short qtab_723_16[1] = {261};
/*
* g723_16_encoder()
*
* Encodes a linear PCM, A-law or u-law input sample and returns its 2-bit code.
* Returns -1 if invalid input coding value.
*/
int
g723_16_encoder(
int sl,
G72x_STATE *state_ptr)
{
short sei, sezi, se, sez; /* ACCUM */
short d; /* SUBTA */
short y; /* MIX */
short sr; /* ADDB */
short dqsez; /* ADDC */
short dq, i;
/* linearize input sample to 14-bit PCM */
sl >>= 2; /* sl of 14-bit dynamic range */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
d = sl - se; /* d = estimation diff. */
/* quantize prediction difference d */
y = step_size(state_ptr); /* quantizer step size */
i = quantize(d, y, qtab_723_16, 1); /* i = ADPCM code */
/* Since quantize() only produces a three level output
* (1, 2, or 3), we must create the fourth one on our own
*/
if (i == 3) /* i code for the zero region */
if ((d & 0x8000) == 0) /* If d > 0, i=3 isn't right... */
i = 0;
dq = reconstruct(i & 2, _dqlntab[i], y); /* quantized diff. */
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */
dqsez = sr + sez - se; /* pole prediction diff. */
update(2, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
return (i);
}
/*
* g723_16_decoder()
*
* Decodes a 2-bit CCITT G.723_16 ADPCM code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
* -1 is returned if the output coding is unknown.
*/
int
g723_16_decoder(
int i,
G72x_STATE *state_ptr)
{
short sezi, sei, sez, se; /* ACCUM */
short y; /* MIX */
short sr; /* ADDB */
short dq;
short dqsez;
i &= 0x03; /* mask to get proper bits */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
y = step_size(state_ptr); /* adaptive quantizer step size */
dq = reconstruct(i & 0x02, _dqlntab[i], y); /* unquantize pred diff */
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */
dqsez = sr - se + sez; /* pole prediction diff. */
update(2, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
/* sr was of 14-bit dynamic range */
return (sr << 2);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: ae265466-c3fc-4f83-bb32-edae488a5ca5
*/

View File

@@ -0,0 +1,146 @@
/*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g723_24.c
*
* Description:
*
* g723_24_encoder(), g723_24_decoder()
*
* These routines comprise an implementation of the CCITT G.723 24 Kbps
* ADPCM coding algorithm. Essentially, this implementation is identical to
* the bit level description except for a few deviations which take advantage
* of workstation attributes, such as hardware 2's complement arithmetic.
*
*/
#include "g72x.h"
#include "g72x_priv.h"
/*
* Maps G.723_24 code word to reconstructed scale factor normalized log
* magnitude values.
*/
static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048};
/* Maps G.723_24 code word to log of scale factor multiplier. */
static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128};
/*
* Maps G.723_24 code words to a set of values whose long and short
* term averages are computed and then compared to give an indication
* how stationary (steady state) the signal is.
*/
static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0};
static short qtab_723_24[3] = {8, 218, 331};
/*
* g723_24_encoder()
*
* Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code.
* Returns -1 if invalid input coding value.
*/
int
g723_24_encoder(
int sl,
G72x_STATE *state_ptr)
{
short sei, sezi, se, sez; /* ACCUM */
short d; /* SUBTA */
short y; /* MIX */
short sr; /* ADDB */
short dqsez; /* ADDC */
short dq, i;
/* linearize input sample to 14-bit PCM */
sl >>= 2; /* sl of 14-bit dynamic range */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
d = sl - se; /* d = estimation diff. */
/* quantize prediction difference d */
y = step_size(state_ptr); /* quantizer step size */
i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */
dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */
dqsez = sr + sez - se; /* pole prediction diff. */
update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
return (i);
}
/*
* g723_24_decoder()
*
* Decodes a 3-bit CCITT G.723_24 ADPCM code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
* -1 is returned if the output coding is unknown.
*/
int
g723_24_decoder(
int i,
G72x_STATE *state_ptr)
{
short sezi, sei, sez, se; /* ACCUM */
short y; /* MIX */
short sr; /* ADDB */
short dq;
short dqsez;
i &= 0x07; /* mask to get proper bits */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
y = step_size(state_ptr); /* adaptive quantizer step size */
dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */
dqsez = sr - se + sez; /* pole prediction diff. */
update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
return (sr << 2); /* sr was of 14-bit dynamic range */
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 75389236-650b-4427-98f3-0df6e8fb24bc
*/

View File

@@ -0,0 +1,160 @@
/*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g723_40.c
*
* Description:
*
* g723_40_encoder(), g723_40_decoder()
*
* These routines comprise an implementation of the CCITT G.723 40Kbps
* ADPCM coding algorithm. Essentially, this implementation is identical to
* the bit level description except for a few deviations which
* take advantage of workstation attributes, such as hardware 2's
* complement arithmetic.
*
* The deviation from the bit level specification (lookup tables),
* preserves the bit level performance specifications.
*
* As outlined in the G.723 Recommendation, the algorithm is broken
* down into modules. Each section of code below is preceded by
* the name of the module which it is implementing.
*
*/
#include "g72x.h"
#include "g72x_priv.h"
/*
* Maps G.723_40 code word to ructeconstructed scale factor normalized log
* magnitude values.
*/
static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318,
358, 395, 429, 459, 488, 514, 539, 566,
566, 539, 514, 488, 459, 429, 395, 358,
318, 274, 224, 169, 104, 28, -66, -2048};
/* Maps G.723_40 code word to log of scale factor multiplier. */
static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200,
4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272,
22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512,
3200, 1856, 1312, 1280, 1248, 768, 448, 448};
/*
* Maps G.723_40 code words to a set of values whose long and short
* term averages are computed and then compared to give an indication
* how stationary (steady state) the signal is.
*/
static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200,
0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00,
0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200,
0x200, 0x200, 0x200, 0, 0, 0, 0, 0};
static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339,
378, 413, 445, 475, 502, 528, 553};
/*
* g723_40_encoder()
*
* Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens
* the resulting 5-bit CCITT G.723 40Kbps code.
* Returns -1 if the input coding value is invalid.
*/
int g723_40_encoder (int sl, G72x_STATE *state_ptr)
{
short sei, sezi, se, sez; /* ACCUM */
short d; /* SUBTA */
short y; /* MIX */
short sr; /* ADDB */
short dqsez; /* ADDC */
short dq, i;
/* linearize input sample to 14-bit PCM */
sl >>= 2; /* sl of 14-bit dynamic range */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
d = sl - se; /* d = estimation difference */
/* quantize prediction difference */
y = step_size(state_ptr); /* adaptive quantizer step size */
i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */
dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */
sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */
dqsez = sr + sez - se; /* dqsez = pole prediction diff. */
update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
return (i);
}
/*
* g723_40_decoder()
*
* Decodes a 5-bit CCITT G.723 40Kbps code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
* -1 is returned if the output coding is unknown.
*/
int g723_40_decoder (int i, G72x_STATE *state_ptr)
{
short sezi, sei, sez, se; /* ACCUM */
short y ; /* MIX */
short sr; /* ADDB */
short dq;
short dqsez;
i &= 0x1f; /* mask to get proper bits */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
y = step_size(state_ptr); /* adaptive quantizer step size */
dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */
sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */
dqsez = sr - se + sez; /* pole prediction diff. */
update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
return (sr << 2); /* sr was of 14-bit dynamic range */
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: eb8d9a00-32bf-4dd2-b287-01b0336d72bf
*/

View File

@@ -0,0 +1,652 @@
/*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g72x.c
*
* Common routines for G.721 and G.723 conversions.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g72x.h"
#include "g72x_priv.h"
static G72x_STATE * g72x_state_new (void) ;
static int unpack_bytes (int bits, int blocksize, const unsigned char * block, short * samples) ;
static int pack_bytes (int bits, const short * samples, unsigned char * block) ;
static
short power2 [15] =
{ 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000
} ;
/*
* quan()
*
* quantizes the input val against the table of size short integers.
* It returns i if table[i - 1] <= val < table[i].
*
* Using linear search for simple coding.
*/
static
int quan (int val, short *table, int size)
{
int i;
for (i = 0; i < size; i++)
if (val < *table++)
break;
return (i);
}
/*
* fmult()
*
* returns the integer product of the 14-bit integer "an" and
* "floating point" representation (4-bit exponent, 6-bit mantessa) "srn".
*/
static
int fmult (int an, int srn)
{
short anmag, anexp, anmant;
short wanexp, wanmant;
short retval;
anmag = (an > 0) ? an : ((-an) & 0x1FFF);
anexp = quan(anmag, power2, 15) - 6;
anmant = (anmag == 0) ? 32 :
(anexp >= 0) ? anmag >> anexp : anmag << -anexp;
wanexp = anexp + ((srn >> 6) & 0xF) - 13;
/*
** The original was :
** wanmant = (anmant * (srn & 0x37) + 0x30) >> 4 ;
** but could see no valid reason for the + 0x30.
** Removed it and it improved the SNR of the codec.
*/
wanmant = (anmant * (srn & 0x37)) >> 4 ;
retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
(wanmant >> -wanexp);
return (((an ^ srn) < 0) ? -retval : retval);
}
static G72x_STATE * g72x_state_new (void)
{ return calloc (1, sizeof (G72x_STATE)) ;
}
/*
* private_init_state()
*
* This routine initializes and/or resets the G72x_PRIVATE structure
* pointed to by 'state_ptr'.
* All the initial state values are specified in the CCITT G.721 document.
*/
void private_init_state (G72x_STATE *state_ptr)
{
int cnta;
state_ptr->yl = 34816;
state_ptr->yu = 544;
state_ptr->dms = 0;
state_ptr->dml = 0;
state_ptr->ap = 0;
for (cnta = 0; cnta < 2; cnta++) {
state_ptr->a[cnta] = 0;
state_ptr->pk[cnta] = 0;
state_ptr->sr[cnta] = 32;
}
for (cnta = 0; cnta < 6; cnta++) {
state_ptr->b[cnta] = 0;
state_ptr->dq[cnta] = 32;
}
state_ptr->td = 0;
} /* private_init_state */
struct g72x_state * g72x_reader_init (int codec, int *blocksize, int *samplesperblock)
{ G72x_STATE *pstate ;
if ((pstate = g72x_state_new ()) == NULL)
return NULL ;
private_init_state (pstate) ;
pstate->encoder = NULL ;
switch (codec)
{ case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */
pstate->decoder = g723_16_decoder ;
*blocksize = G723_16_BYTES_PER_BLOCK ;
*samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 2 ;
pstate->blocksize = G723_16_BYTES_PER_BLOCK ;
pstate->samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
break ;
case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */
pstate->decoder = g723_24_decoder ;
*blocksize = G723_24_BYTES_PER_BLOCK ;
*samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 3 ;
pstate->blocksize = G723_24_BYTES_PER_BLOCK ;
pstate->samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
break ;
case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */
pstate->decoder = g721_decoder ;
*blocksize = G721_32_BYTES_PER_BLOCK ;
*samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 4 ;
pstate->blocksize = G721_32_BYTES_PER_BLOCK ;
pstate->samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
break ;
case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */
pstate->decoder = g723_40_decoder ;
*blocksize = G721_40_BYTES_PER_BLOCK ;
*samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 5 ;
pstate->blocksize = G721_40_BYTES_PER_BLOCK ;
pstate->samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
break ;
default :
free (pstate) ;
return NULL ;
} ;
return pstate ;
} /* g72x_reader_init */
struct g72x_state * g72x_writer_init (int codec, int *blocksize, int *samplesperblock)
{ G72x_STATE *pstate ;
if ((pstate = g72x_state_new ()) == NULL)
return NULL ;
private_init_state (pstate) ;
pstate->decoder = NULL ;
switch (codec)
{ case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */
pstate->encoder = g723_16_encoder ;
*blocksize = G723_16_BYTES_PER_BLOCK ;
*samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 2 ;
pstate->blocksize = G723_16_BYTES_PER_BLOCK ;
pstate->samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
break ;
case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */
pstate->encoder = g723_24_encoder ;
*blocksize = G723_24_BYTES_PER_BLOCK ;
*samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 3 ;
pstate->blocksize = G723_24_BYTES_PER_BLOCK ;
pstate->samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
break ;
case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */
pstate->encoder = g721_encoder ;
*blocksize = G721_32_BYTES_PER_BLOCK ;
*samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 4 ;
pstate->blocksize = G721_32_BYTES_PER_BLOCK ;
pstate->samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
break ;
case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */
pstate->encoder = g723_40_encoder ;
*blocksize = G721_40_BYTES_PER_BLOCK ;
*samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 5 ;
pstate->blocksize = G721_40_BYTES_PER_BLOCK ;
pstate->samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
break ;
default :
free (pstate) ;
return NULL ;
} ;
return pstate ;
} /* g72x_writer_init */
int g72x_decode_block (G72x_STATE *pstate, const unsigned char *block, short *samples)
{ int k, count ;
count = unpack_bytes (pstate->codec_bits, pstate->blocksize, block, samples) ;
for (k = 0 ; k < count ; k++)
samples [k] = pstate->decoder (samples [k], pstate) ;
return 0 ;
} /* g72x_decode_block */
int g72x_encode_block (G72x_STATE *pstate, short *samples, unsigned char *block)
{ int k, count ;
for (k = 0 ; k < pstate->samplesperblock ; k++)
samples [k] = pstate->encoder (samples [k], pstate) ;
count = pack_bytes (pstate->codec_bits, samples, block) ;
return count ;
} /* g72x_encode_block */
/*
* predictor_zero()
*
* computes the estimated signal from 6-zero predictor.
*
*/
int predictor_zero (G72x_STATE *state_ptr)
{
int i;
int sezi;
sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
for (i = 1; i < 6; i++) /* ACCUM */
sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
return (sezi);
}
/*
* predictor_pole()
*
* computes the estimated signal from 2-pole predictor.
*
*/
int predictor_pole(G72x_STATE *state_ptr)
{
return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
}
/*
* step_size()
*
* computes the quantization step size of the adaptive quantizer.
*
*/
int step_size (G72x_STATE *state_ptr)
{
int y;
int dif;
int al;
if (state_ptr->ap >= 256)
return (state_ptr->yu);
else {
y = state_ptr->yl >> 6;
dif = state_ptr->yu - y;
al = state_ptr->ap >> 2;
if (dif > 0)
y += (dif * al) >> 6;
else if (dif < 0)
y += (dif * al + 0x3F) >> 6;
return (y);
}
}
/*
* quantize()
*
* Given a raw sample, 'd', of the difference signal and a
* quantization step size scale factor, 'y', this routine returns the
* ADPCM codeword to which that sample gets quantized. The step
* size scale factor division operation is done in the log base 2 domain
* as a subtraction.
*/
int quantize(
int d, /* Raw difference signal sample */
int y, /* Step size multiplier */
short *table, /* quantization table */
int size) /* table size of short integers */
{
short dqm; /* Magnitude of 'd' */
short expon; /* Integer part of base 2 log of 'd' */
short mant; /* Fractional part of base 2 log */
short dl; /* Log of magnitude of 'd' */
short dln; /* Step size scale factor normalized log */
int i;
/*
* LOG
*
* Compute base 2 log of 'd', and store in 'dl'.
*/
dqm = abs(d);
expon = quan(dqm >> 1, power2, 15);
mant = ((dqm << 7) >> expon) & 0x7F; /* Fractional portion. */
dl = (expon << 7) + mant;
/*
* SUBTB
*
* "Divide" by step size multiplier.
*/
dln = dl - (y >> 2);
/*
* QUAN
*
* Obtain codword i for 'd'.
*/
i = quan(dln, table, size);
if (d < 0) /* take 1's complement of i */
return ((size << 1) + 1 - i);
else if (i == 0) /* take 1's complement of 0 */
return ((size << 1) + 1); /* new in 1988 */
else
return (i);
}
/*
* reconstruct()
*
* Returns reconstructed difference signal 'dq' obtained from
* codeword 'i' and quantization step size scale factor 'y'.
* Multiplication is performed in log base 2 domain as addition.
*/
int
reconstruct(
int sign, /* 0 for non-negative value */
int dqln, /* G.72x codeword */
int y) /* Step size multiplier */
{
short dql; /* Log of 'dq' magnitude */
short dex; /* Integer part of log */
short dqt;
short dq; /* Reconstructed difference signal sample */
dql = dqln + (y >> 2); /* ADDA */
if (dql < 0) {
return ((sign) ? -0x8000 : 0);
} else { /* ANTILOG */
dex = (dql >> 7) & 15;
dqt = 128 + (dql & 127);
dq = (dqt << 7) >> (14 - dex);
return ((sign) ? (dq - 0x8000) : dq);
}
}
/*
* update()
*
* updates the state variables for each output code
*/
void
update(
int code_size, /* distinguish 723_40 with others */
int y, /* quantizer step size */
int wi, /* scale factor multiplier */
int fi, /* for long/short term energies */
int dq, /* quantized prediction difference */
int sr, /* reconstructed signal */
int dqsez, /* difference from 2-pole predictor */
G72x_STATE *state_ptr) /* coder state pointer */
{
int cnt;
short mag, expon; /* Adaptive predictor, FLOAT A */
short a2p = 0; /* LIMC */
short a1ul; /* UPA1 */
short pks1; /* UPA2 */
short fa1;
char tr; /* tone/transition detector */
short ylint, thr2, dqthr;
short ylfrac, thr1;
short pk0;
pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */
mag = dq & 0x7FFF; /* prediction difference magnitude */
/* TRANS */
ylint = state_ptr->yl >> 15; /* exponent part of yl */
ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */
thr1 = (32 + ylfrac) << ylint; /* threshold */
thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */
dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */
if (state_ptr->td == 0) /* signal supposed voice */
tr = 0;
else if (mag <= dqthr) /* supposed data, but small mag */
tr = 0; /* treated as voice */
else /* signal is data (modem) */
tr = 1;
/*
* Quantizer scale factor adaptation.
*/
/* FUNCTW & FILTD & DELAY */
/* update non-steady state step size multiplier */
state_ptr->yu = y + ((wi - y) >> 5);
/* LIMB */
if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */
state_ptr->yu = 544;
else if (state_ptr->yu > 5120)
state_ptr->yu = 5120;
/* FILTE & DELAY */
/* update steady state step size multiplier */
state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
/*
* Adaptive predictor coefficients.
*/
if (tr == 1) { /* reset a's and b's for modem signal */
state_ptr->a[0] = 0;
state_ptr->a[1] = 0;
state_ptr->b[0] = 0;
state_ptr->b[1] = 0;
state_ptr->b[2] = 0;
state_ptr->b[3] = 0;
state_ptr->b[4] = 0;
state_ptr->b[5] = 0;
} else { /* update a's and b's */
pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */
/* update predictor pole a[1] */
a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
if (dqsez != 0) {
fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
if (fa1 < -8191) /* a2p = function of fa1 */
a2p -= 0x100;
else if (fa1 > 8191)
a2p += 0xFF;
else
a2p += fa1 >> 5;
if (pk0 ^ state_ptr->pk[1])
{ /* LIMC */
if (a2p <= -12160)
a2p = -12288;
else if (a2p >= 12416)
a2p = 12288;
else
a2p -= 0x80;
}
else if (a2p <= -12416)
a2p = -12288;
else if (a2p >= 12160)
a2p = 12288;
else
a2p += 0x80;
}
/* TRIGB & DELAY */
state_ptr->a[1] = a2p;
/* UPA1 */
/* update predictor pole a[0] */
state_ptr->a[0] -= state_ptr->a[0] >> 8;
if (dqsez != 0)
{ if (pks1 == 0)
state_ptr->a[0] += 192;
else
state_ptr->a[0] -= 192;
} ;
/* LIMD */
a1ul = 15360 - a2p;
if (state_ptr->a[0] < -a1ul)
state_ptr->a[0] = -a1ul;
else if (state_ptr->a[0] > a1ul)
state_ptr->a[0] = a1ul;
/* UPB : update predictor zeros b[6] */
for (cnt = 0; cnt < 6; cnt++) {
if (code_size == 5) /* for 40Kbps G.723 */
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;
else /* for G.721 and 24Kbps G.723 */
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
if (dq & 0x7FFF) { /* XOR */
if ((dq ^ state_ptr->dq[cnt]) >= 0)
state_ptr->b[cnt] += 128;
else
state_ptr->b[cnt] -= 128;
}
}
}
for (cnt = 5; cnt > 0; cnt--)
state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
/* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
if (mag == 0) {
state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20;
} else {
expon = quan(mag, power2, 15);
state_ptr->dq[0] = (dq >= 0) ?
(expon << 6) + ((mag << 6) >> expon) :
(expon << 6) + ((mag << 6) >> expon) - 0x400;
}
state_ptr->sr[1] = state_ptr->sr[0];
/* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
if (sr == 0) {
state_ptr->sr[0] = 0x20;
} else if (sr > 0) {
expon = quan(sr, power2, 15);
state_ptr->sr[0] = (expon << 6) + ((sr << 6) >> expon);
} else if (sr > -32768) {
mag = -sr;
expon = quan(mag, power2, 15);
state_ptr->sr[0] = (expon << 6) + ((mag << 6) >> expon) - 0x400;
} else
state_ptr->sr[0] = (short) 0xFC20;
/* DELAY A */
state_ptr->pk[1] = state_ptr->pk[0];
state_ptr->pk[0] = pk0;
/* TONE */
if (tr == 1) /* this sample has been treated as data */
state_ptr->td = 0; /* next one will be treated as voice */
else if (a2p < -11776) /* small sample-to-sample correlation */
state_ptr->td = 1; /* signal may be data */
else /* signal is voice */
state_ptr->td = 0;
/*
* Adaptation speed control.
*/
state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */
state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */
if (tr == 1)
state_ptr->ap = 256;
else if (y < 1536) /* SUBTC */
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else if (state_ptr->td == 1)
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
(state_ptr->dml >> 3))
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else
state_ptr->ap += (-state_ptr->ap) >> 4;
return ;
} /* update */
/*------------------------------------------------------------------------------
*/
static int
unpack_bytes (int bits, int blocksize, const unsigned char * block, short * samples)
{ unsigned int in_buffer = 0 ;
unsigned char in_byte ;
int k, in_bits = 0, bindex = 0 ;
for (k = 0 ; bindex <= blocksize && k < G72x_BLOCK_SIZE ; k++)
{ if (in_bits < bits)
{ in_byte = block [bindex++] ;
in_buffer |= (in_byte << in_bits);
in_bits += 8;
}
samples [k] = in_buffer & ((1 << bits) - 1);
in_buffer >>= bits;
in_bits -= bits;
} ;
return k ;
} /* unpack_bytes */
static int
pack_bytes (int bits, const short * samples, unsigned char * block)
{
unsigned int out_buffer = 0 ;
int k, bindex = 0, out_bits = 0 ;
unsigned char out_byte ;
for (k = 0 ; k < G72x_BLOCK_SIZE ; k++)
{ out_buffer |= (samples [k] << out_bits) ;
out_bits += bits ;
if (out_bits >= 8)
{ out_byte = out_buffer & 0xFF ;
out_bits -= 8 ;
out_buffer >>= 8 ;
block [bindex++] = out_byte ;
}
} ;
return bindex ;
} /* pack_bytes */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 6298dc75-fd0f-4062-9b90-f73ed69f22d4
*/

View File

@@ -0,0 +1,99 @@
/*
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This file is not the same as the original file from Sun Microsystems. Nearly
** all the original definitions and function prototypes that were in the file
** of this name have been moved to g72x_priv.h.
*/
#ifndef G72X_HEADER_FILE
#define G72X_HEADER_FILE
/*
** Number of samples per block to process.
** Must be a common multiple of possible bits per sample : 2, 3, 4, 5 and 8.
*/
#define G72x_BLOCK_SIZE (3 * 5 * 8)
/*
** Identifiers for the differing kinds of G72x ADPCM codecs.
** The identifiers also define the number of encoded bits per sample.
*/
enum
{ G723_16_BITS_PER_SAMPLE = 2,
G723_24_BITS_PER_SAMPLE = 3,
G723_40_BITS_PER_SAMPLE = 5,
G721_32_BITS_PER_SAMPLE = 4,
G721_40_BITS_PER_SAMPLE = 5,
G723_16_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE,
G723_24_SAMPLES_PER_BLOCK = G723_24_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_24_BITS_PER_SAMPLE),
G723_40_SAMPLES_PER_BLOCK = G723_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_40_BITS_PER_SAMPLE),
G721_32_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE,
G721_40_SAMPLES_PER_BLOCK = G721_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G721_40_BITS_PER_SAMPLE),
G723_16_BYTES_PER_BLOCK = (G723_16_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8,
G723_24_BYTES_PER_BLOCK = (G723_24_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8,
G723_40_BYTES_PER_BLOCK = (G723_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8,
G721_32_BYTES_PER_BLOCK = (G721_32_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8,
G721_40_BYTES_PER_BLOCK = (G721_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8
} ;
/* Forward declaration of of g72x_state. */
struct g72x_state ;
/* External function definitions. */
struct g72x_state * g72x_reader_init (int codec, int *blocksize, int *samplesperblock) ;
struct g72x_state * g72x_writer_init (int codec, int *blocksize, int *samplesperblock) ;
/*
** Initialize the ADPCM state table for the given codec.
** Return 0 on success, 1 on fail.
*/
int g72x_decode_block (struct g72x_state *pstate, const unsigned char *block, short *samples) ;
/*
** The caller fills data->block with data->bytes bytes before calling the
** function. The value data->bytes must be an integer multiple of
** data->blocksize and be <= data->max_bytes.
** When it returns, the caller can read out data->samples samples.
*/
int g72x_encode_block (struct g72x_state *pstate, short *samples, unsigned char *block) ;
/*
** The caller fills state->samples some integer multiple data->samples_per_block
** (up to G72x_BLOCK_SIZE) samples before calling the function.
** When it returns, the caller can read out bytes encoded bytes.
*/
#endif /* !G72X_HEADER_FILE */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 6ca84e5f-f932-4ba1-87ee-37056d921621
*/

View File

@@ -0,0 +1,118 @@
/*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#ifndef G72X_PRIVATE_H
#define G72X_PRIVATE_H
#ifdef __cplusplus
#error "This code is not designed to be compiled with a C++ compiler."
#endif
/*
** The following is the definition of the state structure used by the
** G.721/G.723 encoder and decoder to preserve their internal state
** between successive calls. The meanings of the majority of the state
** structure fields are explained in detail in the CCITT Recommendation
** G.721. The field names are essentially identical to variable names
** in the bit level description of the coding algorithm included in this
** Recommendation.
*/
struct g72x_state
{ long yl; /* Locked or steady state step size multiplier. */
short yu; /* Unlocked or non-steady state step size multiplier. */
short dms; /* Short term energy estimate. */
short dml; /* Long term energy estimate. */
short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */
short a[2]; /* Coefficients of pole portion of prediction filter. */
short b[6]; /* Coefficients of zero portion of prediction filter. */
short pk[2]; /*
** Signs of previous two samples of a partially
** reconstructed signal.
**/
short dq[6]; /*
** Previous 6 samples of the quantized difference
** signal represented in an internal floating point
** format.
**/
short sr[2]; /*
** Previous 2 samples of the quantized difference
** signal represented in an internal floating point
** format.
*/
char td; /* delayed tone detect, new in 1988 version */
/* The following struct members were added for libsndfile. The original
** code worked by calling a set of functions on a sample by sample basis
** which is slow on architectures like Intel x86. For libsndfile, this
** was changed so that the encoding and decoding routines could work on
** a block of samples at a time to reduce the function call overhead.
*/
int (*encoder) (int, struct g72x_state* state) ;
int (*decoder) (int, struct g72x_state* state) ;
int codec_bits, blocksize, samplesperblock ;
} ;
typedef struct g72x_state G72x_STATE ;
int predictor_zero (G72x_STATE *state_ptr);
int predictor_pole (G72x_STATE *state_ptr);
int step_size (G72x_STATE *state_ptr);
int quantize (int d, int y, short *table, int size);
int reconstruct (int sign, int dqln, int y);
void update (int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, G72x_STATE *state_ptr);
int g721_encoder (int sample, G72x_STATE *state_ptr);
int g721_decoder (int code, G72x_STATE *state_ptr);
int g723_16_encoder (int sample, G72x_STATE *state_ptr);
int g723_16_decoder (int code, G72x_STATE *state_ptr);
int g723_24_encoder (int sample, G72x_STATE *state_ptr);
int g723_24_decoder (int code, G72x_STATE *state_ptr);
int g723_40_encoder (int sample, G72x_STATE *state_ptr);
int g723_40_decoder (int code, G72x_STATE *state_ptr);
void private_init_state (G72x_STATE *state_ptr) ;
#endif /* G72X_PRIVATE_H */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: d9ad4da7-0fa3-471d-8020-720b5cfb5e5b
*/

View File

@@ -0,0 +1,222 @@
/*
** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "g72x.h"
#include "g72x_priv.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846264338
#endif
#define BUFFER_SIZE (1<<14) /* Should be (1<<14) */
#define SAMPLE_RATE 11025
static void g721_test (void) ;
static void g723_test (double margin) ;
static void gen_signal_double (double *data, double scale, int datalen) ;
static int error_function (double data, double orig, double margin) ;
static int oct_save_short (short *a, short *b, int len) ;
int
main (int argc, char *argv [])
{ int bDoAll = 0 ;
int nTests = 0 ;
if (argc != 2)
{ printf ("Usage : %s <test>\n", argv [0]) ;
printf (" Where <test> is one of the following:\n") ;
printf (" g721 - test G721 encoder and decoder\n") ;
printf (" g723 - test G721 encoder and decoder\n") ;
printf (" all - perform all tests\n") ;
exit (1) ;
} ;
bDoAll=!strcmp (argv [1], "all");
if (bDoAll || ! strcmp (argv [1], "g721"))
{ g721_test () ;
nTests++ ;
} ;
if (bDoAll || ! strcmp (argv [1], "g723"))
{ g723_test (0.53) ;
nTests++ ;
} ;
if (nTests == 0)
{ printf ("Mono : ************************************\n") ;
printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
printf ("Mono : ************************************\n") ;
return 1 ;
} ;
return 0 ;
} /* main */
static void
g721_test (void)
{
return ;
} /* g721_test */
static void
g723_test (double margin)
{ static double orig_buffer [BUFFER_SIZE] ;
static short orig [BUFFER_SIZE] ;
static short data [BUFFER_SIZE] ;
G72x_STATE encoder_state, decoder_state ;
long k ;
int code, position, max_err ;
private_init_state (&encoder_state) ;
encoder_state.encoder = g723_24_encoder ;
encoder_state.codec_bits = 3 ;
private_init_state (&decoder_state) ;
decoder_state.decoder = g723_24_decoder ;
decoder_state.codec_bits = 3 ;
memset (data, 0, BUFFER_SIZE * sizeof (short)) ;
memset (orig, 0, BUFFER_SIZE * sizeof (short)) ;
printf (" g723_test : ") ;
fflush (stdout) ;
gen_signal_double (orig_buffer, 32000.0, BUFFER_SIZE) ;
for (k = 0 ; k < BUFFER_SIZE ; k++)
orig [k] = (short) orig_buffer [k] ;
/* Write and read data here. */
position = 0 ;
max_err = 0 ;
for (k = 0 ; k < BUFFER_SIZE ; k++)
{ code = encoder_state.encoder (orig [k], &encoder_state) ;
data [k] = decoder_state.decoder (code, &decoder_state) ;
if (abs (orig [k] - data [k]) > max_err)
{ position = k ;
max_err = abs (orig [k] - data [k]) ;
} ;
} ;
printf ("\n\nMax error of %d at postion %d.\n", max_err, position) ;
for (k = 0 ; k < BUFFER_SIZE ; k++)
{ if (error_function (data [k], orig [k], margin))
{ printf ("Line %d: Incorrect sample A (#%ld : %d should be %d).\n", __LINE__, k, data [k], orig [k]) ;
oct_save_short (orig, data, BUFFER_SIZE) ;
exit (1) ;
} ;
} ;
printf ("ok\n") ;
return ;
} /* g723_test */
#define SIGNAL_MAXVAL 30000.0
#define DECAY_COUNT 1000
static void
gen_signal_double (double *gendata, double scale, int gendatalen)
{ int k, ramplen ;
double amp = 0.0 ;
ramplen = DECAY_COUNT ;
for (k = 0 ; k < gendatalen ; k++)
{ if (k <= ramplen)
amp = scale * k / ((double) ramplen) ;
else if (k > gendatalen - ramplen)
amp = scale * (gendatalen - k) / ((double) ramplen) ;
gendata [k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
+ 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
} ;
return ;
} /* gen_signal_double */
static int
error_function (double data, double orig, double margin)
{ double error ;
if (fabs (orig) <= 500.0)
error = fabs (fabs (data) - fabs(orig)) / 2000.0 ;
else if (fabs (orig) <= 1000.0)
error = fabs (data - orig) / 3000.0 ;
else
error = fabs (data - orig) / fabs (orig) ;
if (error > margin)
{ printf ("\n\n*******************\nError : %f\n", error) ;
return 1 ;
} ;
return 0 ;
} /* error_function */
static int
oct_save_short (short *a, short *b, int len)
{ FILE *file ;
int k ;
if (! (file = fopen ("error.dat", "w")))
return 1 ;
fprintf (file, "# Not created by Octave\n") ;
fprintf (file, "# name: a\n") ;
fprintf (file, "# type: matrix\n") ;
fprintf (file, "# rows: %d\n", len) ;
fprintf (file, "# columns: 1\n") ;
for (k = 0 ; k < len ; k++)
fprintf (file, "% d\n", a [k]) ;
fprintf (file, "# name: b\n") ;
fprintf (file, "# type: matrix\n") ;
fprintf (file, "# rows: %d\n", len) ;
fprintf (file, "# columns: 1\n") ;
for (k = 0 ; k < len ; k++)
fprintf (file, "% d\n", b [k]) ;
fclose (file) ;
return 0 ;
} /* oct_save_short */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 0597b442-a5b0-4abf-92a4-92f6c24e85a6
*/

View File

@@ -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

View File

@@ -0,0 +1,56 @@
2004-05-12 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* gsm610_priv.h
Replace ugly macros with inline functions.
* *.c
Remove temporary variables used by macros and other minor fixes required by
above change.
2003-06-02 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* rpe.c
Renamed variables "exp" to "expon" to avoid shadowed parameter warnigns.
2002-06-08 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* long_term.c
Changes tp removed compiler warnings about shadowed parameters.
2002-06-08 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* private.h
Made declarations of gsm_A, gsm_B, gsm_MIC etc extern. This fixed a compile
problem on MacOSX.
2002-05-10 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* *.[ch]
Removed all pre-ANSI prototype kludges. Removed proto.h and unproto.h.
Started work on making GSM 6.10 files seekable. Currently they are not.
* code.c private.h
Function Gsm_Coder () used a statically defined array. This was obviously
not re-entrant so moved it to struct gsm_state.
2001-09-16 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* code.c
Added #includes for string.h and stdlib.h.
2000-10-27 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* config.h
Removed some commented out #defines (ie //*efine) which were causing problems on
the Sun cc compiler.
2000-02-29 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* private.h
Added #defines to emulate normal compile time options.
2000-02-28 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* everthing
Created this directory and copied files from libgsm.
http://kbs.cs.tu-berlin.de/~jutta/toast.html

View File

@@ -0,0 +1,36 @@
GSM 06.10 13 kbit/s RPE/LTP speech codec
----------------------------------------
All the file in this directory were written by Jutta Degener
and Carsten Borman for The Communications and Operating Systems
Research Group (KBS) at the Technische Universitaet Berlin.
Their work was released under the following license which is
assumed to be compatible with The GNU Lesser General Public License.
----------------------------------------------------------------------------
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 (jutta@cs.tu-berlin.de)
Carsten Bormann (cabo@cs.tu-berlin.de)
----------------------------------------------------------------------------
Jutta Degener and Carsten Bormann's work can be found on their homepage
at:
http://kbs.cs.tu-berlin.de/~jutta/toast.html

View File

@@ -0,0 +1,248 @@
/*
* 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.
*/
/*
* See private.h for the more commonly used macro versions.
*/
#include <stdio.h>
#include <assert.h>
#include "gsm610_priv.h"
#include "gsm.h"
#define saturate(x) \
((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x))
word gsm_add ( word a, word b)
{
longword sum = (longword)a + (longword)b;
return saturate(sum);
}
word gsm_sub ( word a, word b)
{
longword diff = (longword)a - (longword)b;
return saturate(diff);
}
word gsm_mult ( word a, word b)
{
if (a == MIN_WORD && b == MIN_WORD)
return MAX_WORD;
return SASR_L( (longword)a * (longword)b, 15 );
}
word gsm_mult_r ( 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 (word a)
{
return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a;
}
longword gsm_L_mult (word a, word b)
{
assert( a != MIN_WORD || b != MIN_WORD );
return ((longword)a * (longword)b) << 1;
}
longword gsm_L_add ( 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 ( 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 (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 (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_asr (word a, int n)
{
if (n >= 16) return -(a < 0);
if (n <= -16) return 0;
if (n < 0) return a << -n;
return SASR_W (a, (word) n);
}
word gsm_asl (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 (longword a, int n)
{
if (n >= 32) return -(a < 0);
if (n <= -32) return 0;
if (n < 0) return a << -n;
return SASR_L (a, (word) n);
}
/*
** word gsm_asr (word a, int n)
** {
** if (n >= 16) return -(a < 0);
** if (n <= -16) return 0;
** if (n < 0) return a << -n;
**
** # ifdef SASR_W
** 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 (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;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a7398579-e2e1-4733-aa2d-4c6efc0c58ff
*/

View File

@@ -0,0 +1,97 @@
/*
* 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.
*/
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "gsm610_priv.h"
#include "gsm.h"
/*
* 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER
*/
void Gsm_Coder (
struct gsm_state * State,
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 = State->dp0 + 120; /* [ -120...-1 ] */
word * dpp = dp; /* [ 0...39 ] */
word so[160];
Gsm_Preprocess (State, s, so);
Gsm_LPC_Analysis (State, so, LARc);
Gsm_Short_Term_Analysis_Filter (State, LARc, so);
for (k = 0; k <= 3; k++, xMc += 13) {
Gsm_Long_Term_Predictor ( State,
so+k*40, /* d [0..39] IN */
dp, /* dp [-120..-1] IN */
State->e + 5, /* e [0..39] OUT */
dpp, /* dpp [0..39] OUT */
Nc++,
bc++);
Gsm_RPE_Encoding ( /*-S,-*/
State->e + 5, /* e ][0..39][ IN/OUT */
xmaxc++, Mc++, xMc );
/*
* Gsm_Update_of_reconstructed_short_time_residual_signal
* ( dpp, e + 5, dp );
*/
{ register int i;
for (i = 0; i <= 39; i++)
dp[ i ] = GSM_ADD( State->e[5 + i], dpp[i] );
}
dp += 40;
dpp += 40;
}
(void)memcpy( (char *)State->dp0, (char *)(State->dp0 + 160),
120 * sizeof(*State->dp0) );
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: ae8ef1b2-5a1e-4263-94cd-42b15dca81a3
*/

View File

@@ -0,0 +1,33 @@
/*
* 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.
*/
#ifndef CONFIG_H
#define CONFIG_H
#define HAS_STDLIB_H 1 /* /usr/include/stdlib.h */
#define HAS_FCNTL_H 1 /* /usr/include/fcntl.h */
#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 */
#define HAS_STRING_H 1 /* /usr/include/string.h */
#define HAS_UNISTD_H 1 /* /usr/include/unistd.h */
#define HAS_UTIME 1 /* POSIX utime(path, times) */
#define HAS_UTIME_H 1 /* UTIME header file */
#endif /* CONFIG_H */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 5338dfef-8e59-4f51-af47-627c9ea85353
*/

View File

@@ -0,0 +1,67 @@
/*
* 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.
*/
#include <stdio.h>
#include "gsm610_priv.h"
#include "gsm.h"
/*
* 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER
*/
static void Postprocessing (
struct gsm_state * S,
register word * s)
{
register int k;
register word msr = S->msr;
register word tmp;
for (k = 160; k--; s++) {
tmp = GSM_MULT_R( msr, 28180 );
msr = GSM_ADD(*s, tmp); /* Deemphasis */
*s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */
}
S->msr = msr;
}
void Gsm_Decoder (
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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 11ae5b90-2e8b-400b-ac64-a69a1fc6cc41
*/

View File

@@ -0,0 +1,58 @@
/*
* 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.
*/
#ifndef GSM_H
#define GSM_H
#include <stdio.h> /* for FILE * */
/*
* 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
gsm gsm_create (void);
/* Added for libsndfile : May 6, 2002 */
void gsm_init (gsm);
void gsm_destroy (gsm);
int gsm_print (FILE *, gsm, gsm_byte *);
int gsm_option (gsm, int, int *);
void gsm_encode (gsm, gsm_signal *, gsm_byte *);
int gsm_decode (gsm, gsm_byte *, gsm_signal *);
int gsm_explode (gsm, gsm_byte *, gsm_signal *);
void gsm_implode (gsm, gsm_signal *, gsm_byte *);
#endif /* GSM_H */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 8cfc7698-5433-4b6f-aeca-967c6fda4dec
*/

View File

@@ -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.
*/
#ifndef PRIVATE_H
#define PRIVATE_H
/* Added by Erik de Castro Lopo */
#define USE_FLOAT_MUL
#define FAST
#define WAV49
#ifdef __cplusplus
#error "This code is not designed to be compiled with a C++ compiler."
#endif
/* Added by Erik de Castro Lopo */
typedef short word; /* 16 bit signed int */
typedef int longword; /* 32 bit signed int */
typedef unsigned short uword; /* unsigned word */
typedef unsigned int 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 */
/* Moved here from code.c where it was defined as static */
word e[50] ;
} ;
typedef struct gsm_state GSM_STATE ;
#define MIN_WORD (-32767 - 1)
#define MAX_WORD 32767
#define MIN_LONGWORD (-2147483647 - 1)
#define MAX_LONGWORD 2147483647
/* Signed arithmetic shift right. */
static inline word
SASR_W (word x, word by)
{ return (x >> by) ;
} /* SASR */
static inline longword
SASR_L (longword x, word by)
{ return (x >> by) ;
} /* SASR */
/*
* Prototypes from add.c
*/
word gsm_mult (word a, word b) ;
longword gsm_L_mult (word a, word b) ;
word gsm_mult_r (word a, word b) ;
word gsm_div (word num, word denum) ;
word gsm_add (word a, word b ) ;
longword gsm_L_add (longword a, longword b ) ;
word gsm_sub (word a, word b) ;
longword gsm_L_sub (longword a, longword b) ;
word gsm_abs (word a) ;
word gsm_norm (longword a ) ;
longword gsm_L_asl (longword a, int n) ;
word gsm_asl (word a, int n) ;
longword gsm_L_asr (longword a, int n) ;
word gsm_asr (word a, int n) ;
/*
* Inlined functions from add.h
*/
static inline longword
GSM_MULT_R (word a, word b)
{ return (((longword) (a)) * ((longword) (b)) + 16384) >> 15 ;
} /* GSM_MULT_R */
static inline longword
GSM_MULT (word a, word b)
{ return (((longword) (a)) * ((longword) (b))) >> 15 ;
} /* GSM_MULT */
static inline longword
GSM_L_MULT (word a, word b)
{ return ((longword) (a)) * ((longword) (b)) << 1 ;
} /* GSM_L_MULT */
static inline longword
GSM_L_ADD (longword a, longword b)
{ ulongword utmp ;
if (a < 0 && b < 0)
{ utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1) ;
return (utmp >= (ulongword) MAX_LONGWORD) ? MIN_LONGWORD : -(longword)utmp-2 ;
} ;
if (a > 0 && b > 0)
{ utmp = (ulongword) a + (ulongword) b ;
return (utmp >= (ulongword) MAX_LONGWORD) ? MAX_LONGWORD : utmp ;
} ;
return a + b ;
} /* GSM_L_ADD */
static inline longword
GSM_ADD (word a, word b)
{ longword ltmp ;
ltmp = ((longword) a) + ((longword) b) ;
if (ltmp >= MAX_WORD)
return MAX_WORD ;
if (ltmp <= MIN_WORD)
return MIN_WORD ;
return ltmp ;
} /* GSM_ADD */
static inline longword
GSM_SUB (word a, word b)
{ longword ltmp ;
ltmp = ((longword) a) - ((longword) b) ;
if (ltmp >= MAX_WORD)
ltmp = MAX_WORD ;
else if (ltmp <= MIN_WORD)
ltmp = MIN_WORD ;
return ltmp ;
} /* GSM_SUB */
static inline word
GSM_ABS (word a)
{
if (a > 0)
return a ;
if (a == MIN_WORD)
return MAX_WORD ;
return -a ;
} /* GSM_ADD */
/*
* More prototypes from implementations..
*/
void Gsm_Coder (
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 */
void Gsm_Long_Term_Predictor ( /* 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 */
void Gsm_LPC_Analysis (
struct gsm_state * S,
word * s, /* 0..159 signals IN/OUT */
word * LARc) ; /* 0..7 LARc's OUT */
void Gsm_Preprocess (
struct gsm_state * S,
word * s, word * so) ;
void Gsm_Encoding (
struct gsm_state * S,
word * e,
word * ep,
word * xmaxc,
word * Mc,
word * xMc) ;
void Gsm_Short_Term_Analysis_Filter (
struct gsm_state * S,
word * LARc, /* coded log area ratio [0..7] IN */
word * d) ; /* st res. signal [0..159] IN/OUT */
void Gsm_Decoder (
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 */
void Gsm_Decoding (
struct gsm_state * S,
word xmaxcr,
word Mcr,
word * xMcr, /* [0..12] IN */
word * erp) ; /* [0..39] OUT */
void Gsm_Long_Term_Synthesis_Filtering (
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 (
/*-struct gsm_state *S,-*/
word xmaxcr,
word Mcr,
word * xMcr, /* [0..12], 3 bits IN */
word * erp) ; /* [0..39] OUT */
void Gsm_RPE_Encoding (
/*-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 */
void Gsm_Short_Term_Synthesis_Filter (
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 */
void Gsm_Update_of_reconstructed_short_time_residual_signal (
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 */
void gsm_debug_words (char * name, int, int, word *) ;
void gsm_debug_longwords (char * name, int, int, longword *) ;
void gsm_debug_longword (char * name, longword) ;
void gsm_debug_word (char * name, word) ;
#endif /* !NDEBUG */
#endif /* PRIVATE_H */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 8bc5fdf2-e8c8-4686-9bd7-a30b512bef0c
*/

View File

@@ -0,0 +1,44 @@
/*
* 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.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gsm.h"
#include "gsm610_priv.h"
gsm gsm_create (void)
{
gsm r;
r = malloc (sizeof(struct gsm_state));
if (!r) return r;
memset((char *)r, 0, sizeof (struct gsm_state));
r->nrp = 40;
return r;
}
/* Added for libsndfile : May 6, 2002. Not sure if it works. */
void gsm_init (gsm state)
{
memset (state, 0, sizeof (struct gsm_state)) ;
state->nrp = 40 ;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 9fedb6b3-ed99-40c2-aac1-484c536261fe
*/

View File

@@ -0,0 +1,366 @@
/*
* 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.
*/
#include "gsm610_priv.h"
#include "gsm.h"
int gsm_decode (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;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 6a9b6628-821c-4a96-84c1-485ebd35f170
*/

View File

@@ -0,0 +1,31 @@
/*
* 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.
*/
#include "gsm.h"
#include "config.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 (gsm S)
{
if (S) free((char *)S);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f423d09b-6ccc-47e0-9b18-ee1cf7a8e473
*/

View File

@@ -0,0 +1,456 @@
/*
* 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.
*/
#include "gsm610_priv.h"
#include "gsm.h"
void gsm_encode (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);
}
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: cfe9c43d-d97c-4216-b5e5-ccd6a25b582b
*/

View File

@@ -0,0 +1,74 @@
/*
* 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.
*/
#include "gsm610_priv.h"
#include "gsm.h"
int gsm_option (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;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 963ff156-506f-4359-9145-371e9060b030
*/

View File

@@ -0,0 +1,951 @@
/*
* 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.
*/
#include <stdio.h>
#include <assert.h>
#include "gsm610_priv.h"
#include "gsm.h"
/*
* 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 (
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_W(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_W( 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 (
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_W( d[k], scal );
/* 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++) {
# 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;
}
}
*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_W( 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( L_max << temp, 16 );
S = SASR_L( 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 (
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_W(dmax, scal) * st->ltp_cut / 100;
/* Initialization of a working array wt
*/
for (k = 0; k < 40; k++) {
register word w = SASR_W( 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_W( 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 (
register word * din, /* [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 = din [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_W (din [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_W( 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 ( L_max << temp, 16 );
S = SASR_L ( 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 (
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 (
register word * din, /* [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) din [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 (
word bc, /* IN */
word Nc, /* IN */
register word * dp, /* previous d [-120..-1] IN */
register word * d, /* d [0..39] IN */
register word * dpp, /* estimate [0..39] OUT */
register word * e /* long term res. signal [0..39] OUT */
)
/*
* In this part, we have to decode the bc parameter to compute
* the samples of the estimate dpp[0..39]. The decoding of bc needs the
* use of table 4.3b. The long term residual signal e[0..39]
* is then calculated to be fed to the RPE encoding section.
*/
{
register int k;
# undef STEP
# define STEP(BP) \
for (k = 0; k <= 39; k++) { \
dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \
e[k] = GSM_SUB( d[k], dpp[k] ); \
}
switch (bc) {
case 0: STEP( 3277 ); break;
case 1: STEP( 11469 ); break;
case 2: STEP( 21299 ); break;
case 3: STEP( 32767 ); break;
}
}
void Gsm_Long_Term_Predictor ( /* 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 (
struct gsm_state * S,
word Ncr,
word bcr,
register word * erp, /* [0..39] IN */
register word * drp /* [-120..-1] IN, [-120..40] OUT */
)
/*
* This procedure uses the bcr and Ncr parameter to realize the
* long term synthesis filtering. The decoding of bcr needs
* table 4.3b.
*/
{
register int k;
word brp, drpp, Nr;
/* Check the limits of Nr.
*/
Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr;
S->nrp = Nr;
assert(Nr >= 40 && Nr <= 120);
/* Decoding of the LTP gain bcr
*/
brp = gsm_QLB[ bcr ];
/* Computation of the reconstructed short term residual
* signal drp[0..39]
*/
assert(brp != MIN_WORD);
for (k = 0; k <= 39; k++) {
drpp = GSM_MULT_R( brp, drp[ k - Nr ] );
drp[k] = GSM_ADD( erp[k], drpp );
}
/*
* Update of the reconstructed short term residual signal
* drp[ -1..-120 ]
*/
for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ];
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: b369b90d-0284-42a0-87b0-99a25bbd93ac
*/

View File

@@ -0,0 +1,341 @@
/*
* 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.
*/
#include <stdio.h>
#include <assert.h>
#include "gsm610_priv.h"
#include "gsm.h"
/*
* 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION
*/
/* 4.2.4 */
static void Autocorrelation (
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.
*/
smax = 0;
for (k = 0; k <= 159; k++) {
temp = GSM_ABS( s[k] );
if (temp > smax) smax = temp;
}
/* 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) {
# 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
}
# ifdef USE_FLOAT_MUL
else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k];
# endif
/* Compute the L_ACF[..].
*/
{
# 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) ;
}
/* Rescaling of the array s[0..159]
*/
if (scalauto > 0) {
assert(scalauto <= 4);
for (k = 160; k--; *s++ <<= scalauto) ;
}
}
#if defined(USE_FLOAT_MUL) && defined(FAST)
static void Fast_Autocorrelation (
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 (
longword * L_ACF, /* 0...8 IN */
register word * r /* 0...7 OUT */
)
{
register int i, m, n;
register word temp;
word ACF[9]; /* 0..8 */
word P[ 9]; /* 0..8 */
word K[ 9]; /* 2..8 */
/* Schur recursion with 16 bits arithmetic.
*/
if (L_ACF[0] == 0) {
for (i = 8; i--; *r++ = 0) ;
return;
}
assert( L_ACF[0] != 0 );
temp = gsm_norm( L_ACF[0] );
assert(temp >= 0 && temp < 32);
/* ? overflow ? */
for (i = 0; i <= 8; i++) ACF[i] = SASR_L( 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 (
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 (
register word * LAR /* [0..7] IN/OUT */
)
{
register word temp;
/* This procedure needs four tables; the following equations
* give the optimum scaling for the constants:
*
* A[0..7] = integer( real_A[0..7] * 1024 )
* B[0..7] = integer( real_B[0..7] * 512 )
* MAC[0..7] = maximum of the LARc[0..7]
* MIC[0..7] = minimum of the LARc[0..7]
*/
# undef STEP
# define STEP( A, B, MAC, MIC ) \
temp = GSM_MULT( A, *LAR ); \
temp = GSM_ADD( temp, B ); \
temp = GSM_ADD( temp, 256 ); \
temp = SASR_W( 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 (
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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 63146664-a002-4e1e-8b7b-f0cc8a6a53da
*/

View File

@@ -0,0 +1,115 @@
/*
* 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.
*/
#include <stdio.h>
#include <assert.h>
#include "gsm610_priv.h"
#include "gsm.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 (
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;
longword L_s2;
longword L_temp;
word msp, lsp;
word SO;
register int k = 160;
while (k--) {
/* 4.2.1 Downscaling of the input signal
*/
SO = SASR_W( *s, 3 ) << 2;
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);
/* Compute the recursive part
*/
L_s2 = s1;
L_s2 <<= 15;
/* Execution of a 31 bv 16 bits multiplication
*/
msp = SASR_L( L_z2, 15 );
lsp = L_z2-((longword)msp<<15); /* 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 );
/* 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( L_temp, 15 );
*so++ = GSM_ADD( mp, msp );
}
S->z1 = z1;
S->L_z2 = L_z2;
S->mp = mp;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: b760b0d9-3a05-4da3-9dc9-441ffb905d87
*/

View File

@@ -0,0 +1,490 @@
/*
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
*/
#include <stdio.h>
#include <assert.h>
#include "gsm610_priv.h"
#include "gsm.h"
/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION
*/
/* 4.2.13 */
static void Weighting_filter (
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( L_result, 13 );
x[k] = ( L_result < MIN_WORD ? MIN_WORD
: (L_result > MAX_WORD ? MAX_WORD : L_result ));
}
}
/* 4.2.14 */
static void RPE_grid_selection (
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_W( 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_W( 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 (
word xmaxc, /* IN */
word * expon_out, /* OUT */
word * mant_out ) /* OUT */
{
word expon, mant;
/* Compute expononent and mantissa of the decoded version of xmaxc
*/
expon = 0;
if (xmaxc > 15) expon = SASR_W(xmaxc, 3) - 1;
mant = xmaxc - (expon << 3);
if (mant == 0) {
expon = -4;
mant = 7;
}
else {
while (mant <= 7) {
mant = mant << 1 | 1;
expon--;
}
mant -= 8;
}
assert( expon >= -4 && expon <= 6 );
assert( mant >= 0 && mant <= 7 );
*expon_out = expon;
*mant_out = mant;
}
static void APCM_quantization (
word * xM, /* [0..12] IN */
word * xMc, /* [0..12] OUT */
word * mant_out, /* OUT */
word * expon_out, /* OUT */
word * xmaxc_out /* OUT */
)
{
int i, itest;
word xmax, xmaxc, temp, temp1, temp2;
word expon, 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.
*/
expon = 0;
temp = SASR_W( xmax, 9 );
itest = 0;
for (i = 0; i <= 5; i++) {
itest |= (temp <= 0);
temp = SASR_W( temp, 1 );
assert(expon <= 5);
if (itest == 0) expon++; /* expon = add (expon, 1) */
}
assert(expon <= 6 && expon >= 0);
temp = expon + 5;
assert(temp <= 11 && temp >= 0);
xmaxc = gsm_add( SASR_W(xmax, temp), (word) (expon << 3) );
/* Quantizing and coding of the xM[0..12] RPE sequence
* to get the xMc[0..12]
*/
APCM_quantization_xmaxc_to_exp_mant( xmaxc, &expon, &mant );
/* This computation uses the fact that the decoded version of xmaxc
* can be calculated by using the expononent 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 expononent. 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( expon <= 4096 && expon >= -4096);
assert( mant >= 0 && mant <= 7 );
temp1 = 6 - expon; /* normalization by the expononent */
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_W(temp, 12);
xMc[i] = temp + 4; /* see note below */
}
/* NOTE: This equation is used to make all the xMc[i] positive.
*/
*mant_out = mant;
*expon_out = expon;
*xmaxc_out = xmaxc;
}
/* 4.2.16 */
static void APCM_inverse_quantization (
register word * xMc, /* [0..12] IN */
word mant,
word expon,
register word * xMp) /* [0..12] OUT */
/*
* This part is for decoding the RPE sequence of coded xMc[0..12]
* samples to obtain the xMp[0..12] array. Table 4.6 is used to get
* the mantissa of xmaxc (FAC[0..7]).
*/
{
int i;
word temp, temp1, temp2, temp3;
assert( mant >= 0 && mant <= 7 );
temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */
temp2 = gsm_sub( 6, expon ); /* 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 (
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 (
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 (
/*-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, expon;
Weighting_filter(e, x);
RPE_grid_selection(x, xM, Mc);
APCM_quantization( xM, xMc, &mant, &expon, xmaxc);
APCM_inverse_quantization( xMc, mant, expon, xMp);
RPE_grid_positioning( *Mc, xMp, e );
}
void Gsm_RPE_Decoding (
/*-struct gsm_state * S,-*/
word xmaxcr,
word Mcr,
word * xMcr, /* [0..12], 3 bits IN */
word * erp /* [0..39] OUT */
)
{
word expon, mant;
word xMp[ 13 ];
APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &expon, &mant );
APCM_inverse_quantization( xMcr, mant, expon, xMp );
RPE_grid_positioning( Mcr, xMp, erp );
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 82005b9e-1560-4e94-9ddb-00cb14867295
*/

View File

@@ -0,0 +1,427 @@
/*
* 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.
*/
#include <stdio.h>
#include <assert.h>
#include "gsm610_priv.h"
#include "gsm.h"
/*
* SHORT TERM ANALYSIS FILTERING SECTION
*/
/* 4.2.8 */
static void Decoding_of_the_coded_Log_Area_Ratios (
word * LARc, /* coded log area ratio [0..7] IN */
word * LARpp) /* out: decoded .. */
{
register word temp1 /* , temp2 */;
/* This procedure requires for efficient implementation
* two tables.
*
* INVA[1..8] = integer( (32768 * 8) / real_A[1..8])
* MIC[1..8] = minimum value of the LARc[1..8]
*/
/* Compute the LARpp[1..8]
*/
/* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) {
*
* temp1 = GSM_ADD( *LARc, *MIC ) << 10;
* temp2 = *B << 1;
* temp1 = GSM_SUB( temp1, temp2 );
*
* assert(*INVA != MIN_WORD);
*
* temp1 = GSM_MULT_R( *INVA, temp1 );
* *LARpp = GSM_ADD( temp1, temp1 );
* }
*/
#undef STEP
#define STEP( B, MIC, INVA ) \
temp1 = GSM_ADD( *LARc++, MIC ) << 10; \
temp1 = GSM_SUB( temp1, B << 1 ); \
temp1 = GSM_MULT_R( INVA, temp1 ); \
*LARpp++ = GSM_ADD( temp1, temp1 );
STEP( 0, -32, 13107 );
STEP( 0, -32, 13107 );
STEP( 2048, -16, 13107 );
STEP( -2560, -16, 13107 );
STEP( 94, -8, 19223 );
STEP( -1792, -8, 17476 );
STEP( -341, -4, 31454 );
STEP( -1144, -4, 29708 );
/* NOTE: the addition of *MIC is used to restore
* the sign of *LARc.
*/
}
/* 4.2.9 */
/* Computation of the quantized reflection coefficients
*/
/* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8]
*/
/*
* Within each frame of 160 analyzed speech samples the short term
* analysis and synthesis filters operate with four different sets of
* coefficients, derived from the previous set of decoded LARs(LARpp(j-1))
* and the actual set of decoded LARs (LARpp(j))
*
* (Initial value: LARpp(j-1)[1..8] = 0.)
*/
static void Coefficients_0_12 (
register word * LARpp_j_1,
register word * LARpp_j,
register word * LARp)
{
register int i;
for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) {
*LARp = GSM_ADD( SASR_W( *LARpp_j_1, 2 ), SASR_W( *LARpp_j, 2 ));
*LARp = GSM_ADD( *LARp, SASR_W( *LARpp_j_1, 1));
}
}
static void Coefficients_13_26 (
register word * LARpp_j_1,
register word * LARpp_j,
register word * LARp)
{
register int i;
for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) {
*LARp = GSM_ADD( SASR_W( *LARpp_j_1, 1), SASR_W( *LARpp_j, 1 ));
}
}
static void Coefficients_27_39 (
register word * LARpp_j_1,
register word * LARpp_j,
register word * LARp)
{
register int i;
for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) {
*LARp = GSM_ADD( SASR_W( *LARpp_j_1, 2 ), SASR_W( *LARpp_j, 2 ));
*LARp = GSM_ADD( *LARp, SASR_W( *LARpp_j, 1 ));
}
}
static void Coefficients_40_159 (
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 (
register word * LARp) /* [0..7] IN/OUT */
/*
* The input of this procedure is the interpolated LARp[0..7] array.
* The reflection coefficients, rp[i], are used in the analysis
* filter and in the synthesis filter.
*/
{
register int i;
register word temp;
for (i = 1; i <= 8; i++, LARp++) {
/* temp = GSM_ABS( *LARp );
*
* if (temp < 11059) temp <<= 1;
* else if (temp < 20070) temp += 11059;
* else temp = GSM_ADD( temp >> 2, 26112 );
*
* *LARp = *LARp < 0 ? -temp : temp;
*/
if (*LARp < 0) {
temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp);
*LARp = - ((temp < 11059) ? temp << 1
: ((temp < 20070) ? temp + 11059
: GSM_ADD( (word) (temp >> 2), (word) 26112 )));
} else {
temp = *LARp;
*LARp = (temp < 11059) ? temp << 1
: ((temp < 20070) ? temp + 11059
: GSM_ADD( (word) (temp >> 2), (word) 26112 ));
}
}
}
/* 4.2.10 */
static void Short_term_analysis_filtering (
struct gsm_state * S,
register word * rp, /* [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 u[0..7] in memory for each call.
*/
{
register word * u = S->u;
register int i;
register word di, zzz, ui, sav, rpi;
for (; k_n--; s++) {
di = sav = *s;
for (i = 0; i < 8; i++) { /* YYY */
ui = u[i];
rpi = rp[i];
u[i] = sav;
zzz = GSM_MULT_R(rpi, di);
sav = GSM_ADD( ui, zzz);
zzz = GSM_MULT_R(rpi, ui);
di = GSM_ADD( di, zzz );
}
*s = di;
}
}
#if defined(USE_FLOAT_MUL) && defined(FAST)
static void Fast_Short_term_analysis_filtering (
struct gsm_state * S,
register word * rp, /* [0..7] IN */
register int k_n, /* k_end - k_start */
register word * s /* [0..n-1] IN/OUT */
)
{
register word * u = S->u;
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)) */
static void Short_term_synthesis_filtering (
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 word sri, tmp1, tmp2;
while (k--) {
sri = *wt++;
for (i = 8; i--;) {
/* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) );
*/
tmp1 = rrp[i];
tmp2 = v[i];
tmp2 = ( tmp1 == MIN_WORD && tmp2 == MIN_WORD
? MAX_WORD
: 0x0FFFF & (( (longword)tmp1 * (longword)tmp2
+ 16384) >> 15)) ;
sri = GSM_SUB( sri, tmp2 );
/* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) );
*/
tmp1 = ( tmp1 == MIN_WORD && sri == MIN_WORD
? MAX_WORD
: 0x0FFFF & (( (longword)tmp1 * (longword)sri
+ 16384) >> 15)) ;
v[i+1] = GSM_ADD( v[i], tmp1);
}
*sr++ = v[0] = sri;
}
}
#if defined(FAST) && defined(USE_FLOAT_MUL)
static void Fast_Short_term_synthesis_filtering (
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 (
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, LARp, 13, s);
Coefficients_13_26( LARpp_j_1, LARpp_j, LARp);
LARp_to_rp( LARp );
FILTER( S, LARp, 14, s + 13);
Coefficients_27_39( LARpp_j_1, LARpp_j, LARp);
LARp_to_rp( LARp );
FILTER( S, LARp, 13, s + 27);
Coefficients_40_159( LARpp_j, LARp);
LARp_to_rp( LARp );
FILTER( S, LARp, 120, s + 40);
}
void Gsm_Short_Term_Synthesis_Filter (
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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 019ac7ba-c6dd-4540-abf0-8644b6c4a633
*/

View File

@@ -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.
*/
/* 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 "gsm610_priv.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 };
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 8957c531-e6b0-4097-9202-da7ca42729ca
*/

View File

@@ -0,0 +1,36 @@
# Auto-generated by create_symbols_file.py
_sf_command
_sf_open
_sf_close
_sf_seek
_sf_error
_sf_perror
_sf_error_str
_sf_error_number
_sf_format_check
_sf_read_raw
_sf_readf_short
_sf_readf_int
_sf_readf_float
_sf_readf_double
_sf_read_short
_sf_read_int
_sf_read_float
_sf_read_double
_sf_write_raw
_sf_writef_short
_sf_writef_int
_sf_writef_float
_sf_writef_double
_sf_write_short
_sf_write_int
_sf_write_float
_sf_write_double
_sf_strerror
_sf_get_string
_sf_set_string
_sf_open_fd
_sf_open_virtual
_sf_write_sync

View File

@@ -0,0 +1,42 @@
# Auto-generated by create_symbols_file.py
libsndfile.so.1.0
{
global:
sf_command ;
sf_open ;
sf_close ;
sf_seek ;
sf_error ;
sf_perror ;
sf_error_str ;
sf_error_number ;
sf_format_check ;
sf_read_raw ;
sf_readf_short ;
sf_readf_int ;
sf_readf_float ;
sf_readf_double ;
sf_read_short ;
sf_read_int ;
sf_read_float ;
sf_read_double ;
sf_write_raw ;
sf_writef_short ;
sf_writef_int ;
sf_writef_float ;
sf_writef_double ;
sf_write_short ;
sf_write_int ;
sf_write_float ;
sf_write_double ;
sf_strerror ;
sf_get_string ;
sf_set_string ;
sf_open_fd ;
sf_open_virtual ;
sf_write_sync ;
local:
* ;
} ;

1482
libs/libsndfile/src/aiff.c Normal file

File diff suppressed because it is too large Load Diff

544
libs/libsndfile/src/alaw.c Normal file
View File

@@ -0,0 +1,544 @@
/*
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sndfile.h"
#include "float_cast.h"
#include "common.h"
static sf_count_t alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static void alaw2s_array (unsigned char *buffer, int count, short *ptr) ;
static void alaw2i_array (unsigned char *buffer, int count, int *ptr) ;
static void alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) ;
static void alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact) ;
static void s2alaw_array (const short *buffer, int count, unsigned char *ptr) ;
static void i2alaw_array (const int *buffer, int count, unsigned char *ptr) ;
static void f2alaw_array (const float *buffer, int count, unsigned char *ptr, float normfact) ;
static void d2alaw_array (const double *buffer, int count, unsigned char *ptr, double normfact) ;
int
alaw_init (SF_PRIVATE *psf)
{
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
{ psf->read_short = alaw_read_alaw2s ;
psf->read_int = alaw_read_alaw2i ;
psf->read_float = alaw_read_alaw2f ;
psf->read_double = alaw_read_alaw2d ;
} ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->write_short = alaw_write_s2alaw ;
psf->write_int = alaw_write_i2alaw ;
psf->write_float = alaw_write_f2alaw ;
psf->write_double = alaw_write_d2alaw ;
} ;
psf->bytewidth = 1 ;
psf->blockwidth = psf->sf.channels ;
if (psf->filelength > psf->dataoffset)
psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ;
else
psf->datalength = 0 ;
psf->sf.frames = psf->datalength / psf->blockwidth ;
return 0 ;
} /* alaw_init */
/*==============================================================================
* Private static functions and data.
*/
static
short alaw_decode [256] =
{ -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
-3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
-22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
-30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
-11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
-15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
-344, -328, -376, -360, -280, -264, -312, -296,
-472, -456, -504, -488, -408, -392, -440, -424,
-88, -72, -120, -104, -24, -8, -56, -40,
-216, -200, -248, -232, -152, -136, -184, -168,
-1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
-688, -656, -752, -720, -560, -528, -624, -592,
-944, -912, -1008, -976, -816, -784, -880, -848,
5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
344, 328, 376, 360, 280, 264, 312, 296,
472, 456, 504, 488, 408, 392, 440, 424,
88, 72, 120, 104, 24, 8, 56, 40,
216, 200, 248, 232, 152, 136, 184, 168,
1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
688, 656, 752, 720, 560, 528, 624, 592,
944, 912, 1008, 976, 816, 784, 880, 848
} ; /* alaw_decode */
static
unsigned char alaw_encode [2048 + 1] =
{ 0xd5, 0xd4, 0xd7, 0xd6, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde,
0xd9, 0xd8, 0xdb, 0xda, 0xc5, 0xc4, 0xc7, 0xc6, 0xc1, 0xc0, 0xc3, 0xc2,
0xcd, 0xcc, 0xcf, 0xce, 0xc9, 0xc8, 0xcb, 0xca, 0xf5, 0xf5, 0xf4, 0xf4,
0xf7, 0xf7, 0xf6, 0xf6, 0xf1, 0xf1, 0xf0, 0xf0, 0xf3, 0xf3, 0xf2, 0xf2,
0xfd, 0xfd, 0xfc, 0xfc, 0xff, 0xff, 0xfe, 0xfe, 0xf9, 0xf9, 0xf8, 0xf8,
0xfb, 0xfb, 0xfa, 0xfa, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4,
0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe1, 0xe1, 0xe1, 0xe1,
0xe0, 0xe0, 0xe0, 0xe0, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2,
0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xef, 0xef, 0xef, 0xef,
0xee, 0xee, 0xee, 0xee, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8,
0xeb, 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0x95, 0x95, 0x95, 0x95,
0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96,
0x96, 0x96, 0x96, 0x96, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x93,
0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c,
0x9c, 0x9c, 0x9c, 0x9c, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x99, 0x99, 0x99, 0x99,
0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a,
0x9a, 0x9a, 0x9a, 0x9a, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84,
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8f, 0x8f, 0x8f, 0x8f,
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
0x8e, 0x8e, 0x8e, 0x8e, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0xb5, 0xb5, 0xb5, 0xb5,
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
0xb5, 0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6,
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
0xb6, 0xb6, 0xb6, 0xb6, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb3, 0xb3, 0xb3, 0xb3,
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
0xb3, 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc,
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
0xbc, 0xbc, 0xbc, 0xbc, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xb9, 0xb9, 0xb9, 0xb9,
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
0xb9, 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba,
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
0xba, 0xba, 0xba, 0xba, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4,
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
0xa0, 0xa0, 0xa0, 0xa0, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2,
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xaf, 0xaf, 0xaf, 0xaf,
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
0xae, 0xae, 0xae, 0xae, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8,
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a
} ; /* alaw_encode */
static inline void
alaw2s_array (unsigned char *buffer, int count, short *ptr)
{ while (--count >= 0)
ptr [count] = alaw_decode [(int) buffer [count]] ;
} /* alaw2s_array */
static inline void
alaw2i_array (unsigned char *buffer, int count, int *ptr)
{ while (--count >= 0)
ptr [count] = alaw_decode [(int) buffer [count]] << 16 ;
} /* alaw2i_array */
static inline void
alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact)
{ while (--count >= 0)
ptr [count] = normfact * alaw_decode [(int) buffer [count]] ;
} /* alaw2f_array */
static inline void
alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact)
{ while (--count >= 0)
ptr [count] = normfact * alaw_decode [(int) buffer [count]] ;
} /* alaw2d_array */
static inline void
s2alaw_array (const short *ptr, int count, unsigned char *buffer)
{ while (--count >= 0)
{ if (ptr [count] >= 0)
buffer [count] = alaw_encode [ptr [count] / 16] ;
else
buffer [count] = 0x7F & alaw_encode [ptr [count] / -16] ;
} ;
} /* s2alaw_array */
static inline void
i2alaw_array (const int *ptr, int count, unsigned char *buffer)
{ while (--count >= 0)
{ if (ptr [count] >= 0)
buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ;
else
buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ;
} ;
} /* i2alaw_array */
static inline void
f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact)
{ while (--count >= 0)
{ if (ptr [count] >= 0)
buffer [count] = alaw_encode [lrintf (normfact * ptr [count])] ;
else
buffer [count] = 0x7F & alaw_encode [- lrintf (normfact * ptr [count])] ;
} ;
} /* f2alaw_array */
static inline void
d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact)
{ while (--count >= 0)
{ if (ptr [count] >= 0)
buffer [count] = alaw_encode [lrint (normfact * ptr [count])] ;
else
buffer [count] = 0x7F & alaw_encode [- lrint (normfact * ptr [count])] ;
} ;
} /* d2alaw_array */
/*==============================================================================
*/
static sf_count_t
alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
alaw2s_array (psf->u.ucbuf, readcount, ptr + total) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* alaw_read_alaw2s */
static sf_count_t
alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
alaw2i_array (psf->u.ucbuf, readcount, ptr + total) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* alaw_read_alaw2i */
static sf_count_t
alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
float normfact ;
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
alaw2f_array (psf->u.ucbuf, readcount, ptr + total, normfact) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* alaw_read_alaw2f */
static sf_count_t
alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
double normfact ;
normfact = (psf->norm_double) ? 1.0 / ((double) 0x8000) : 1.0 ;
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
alaw2d_array (psf->u.ucbuf, readcount, ptr + total, normfact) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* alaw_read_alaw2d */
/*=============================================================================================
*/
static sf_count_t
alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
s2alaw_array (ptr + total, bufferlen, psf->u.ucbuf) ;
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* alaw_write_s2alaw */
static sf_count_t
alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
i2alaw_array (ptr + total, bufferlen, psf->u.ucbuf) ;
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* alaw_write_i2alaw */
static sf_count_t
alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
float normfact ;
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) / 16.0 : 1.0 / 16 ;
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
f2alaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ;
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* alaw_write_f2alaw */
static sf_count_t
alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
double normfact ;
normfact = (psf->norm_double) ? (1.0 * 0x7FFF) / 16.0 : 1.0 / 16.0 ;
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
d2alaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ;
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* alaw_write_d2alaw */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 289ccfc2-42a6-4f1f-a29f-4dcc9bfa8752
*/

453
libs/libsndfile/src/au.c Normal file
View File

@@ -0,0 +1,453 @@
/*
** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define DOTSND_MARKER (MAKE_MARKER ('.', 's', 'n', 'd'))
#define DNSDOT_MARKER (MAKE_MARKER ('d', 'n', 's', '.'))
#define AU_DATA_OFFSET 24
/*------------------------------------------------------------------------------
** Known AU file encoding types.
*/
enum
{ AU_ENCODING_ULAW_8 = 1, /* 8-bit u-law samples */
AU_ENCODING_PCM_8 = 2, /* 8-bit linear samples */
AU_ENCODING_PCM_16 = 3, /* 16-bit linear samples */
AU_ENCODING_PCM_24 = 4, /* 24-bit linear samples */
AU_ENCODING_PCM_32 = 5, /* 32-bit linear samples */
AU_ENCODING_FLOAT = 6, /* floating-point samples */
AU_ENCODING_DOUBLE = 7, /* double-precision float samples */
AU_ENCODING_INDIRECT = 8, /* fragmented sampled data */
AU_ENCODING_NESTED = 9, /* ? */
AU_ENCODING_DSP_CORE = 10, /* DSP program */
AU_ENCODING_DSP_DATA_8 = 11, /* 8-bit fixed-point samples */
AU_ENCODING_DSP_DATA_16 = 12, /* 16-bit fixed-point samples */
AU_ENCODING_DSP_DATA_24 = 13, /* 24-bit fixed-point samples */
AU_ENCODING_DSP_DATA_32 = 14, /* 32-bit fixed-point samples */
AU_ENCODING_DISPLAY = 16, /* non-audio display data */
AU_ENCODING_MULAW_SQUELCH = 17, /* ? */
AU_ENCODING_EMPHASIZED = 18, /* 16-bit linear with emphasis */
AU_ENCODING_NEXT = 19, /* 16-bit linear with compression (NEXT) */
AU_ENCODING_COMPRESSED_EMPHASIZED = 20, /* A combination of the two above */
AU_ENCODING_DSP_COMMANDS = 21, /* Music Kit DSP commands */
AU_ENCODING_DSP_COMMANDS_SAMPLES = 22, /* ? */
AU_ENCODING_ADPCM_G721_32 = 23, /* G721 32 kbs ADPCM - 4 bits per sample. */
AU_ENCODING_ADPCM_G722 = 24, /* G722 64 kbs ADPCM */
AU_ENCODING_ADPCM_G723_24 = 25, /* G723 24 kbs ADPCM - 3 bits per sample. */
AU_ENCODING_ADPCM_G723_40 = 26, /* G723 40 kbs ADPCM - 5 bits per sample. */
AU_ENCODING_ALAW_8 = 27
} ;
/*------------------------------------------------------------------------------
** Typedefs.
*/
typedef struct
{ int dataoffset ;
int datasize ;
int encoding ;
int samplerate ;
int channels ;
} AU_FMT ;
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int au_close (SF_PRIVATE *psf) ;
static int au_format_to_encoding (int format) ;
static int au_write_header (SF_PRIVATE *psf, int calc_length) ;
static int au_read_header (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
au_open (SF_PRIVATE *psf)
{ int subformat ;
int error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = au_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AU)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)
psf->endian = SF_ENDIAN_LITTLE ;
else if (psf->endian != SF_ENDIAN_LITTLE)
psf->endian = SF_ENDIAN_BIG ;
if (au_write_header (psf, SF_FALSE))
return psf->error ;
psf->write_header = au_write_header ;
} ;
psf->container_close = au_close ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
switch (subformat)
{ case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */
ulaw_init (psf) ;
break ;
case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
error = pcm_init (psf) ;
break ;
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */
case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */
error = pcm_init (psf) ;
break ;
case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */
alaw_init (psf) ;
break ;
/* Lite remove start */
case SF_FORMAT_FLOAT : /* 32-bit floats. */
error = float32_init (psf) ;
break ;
case SF_FORMAT_DOUBLE : /* 64-bit double precision floats. */
error = double64_init (psf) ;
break ;
case SF_FORMAT_G721_32 :
error = g72x_init (psf) ;
psf->sf.seekable = SF_FALSE ;
break ;
case SF_FORMAT_G723_24 :
error = g72x_init (psf) ;
psf->sf.seekable = SF_FALSE ;
break ;
case SF_FORMAT_G723_40 :
error = g72x_init (psf) ;
psf->sf.seekable = SF_FALSE ;
break ;
/* Lite remove end */
default : break ;
} ;
return error ;
} /* au_open */
/*------------------------------------------------------------------------------
*/
static int
au_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
au_write_header (psf, SF_TRUE) ;
return 0 ;
} /* au_close */
static int
au_write_header (SF_PRIVATE *psf, int calc_length)
{ sf_count_t current ;
int encoding, datalength ;
if (psf->pipeoffset > 0)
return 0 ;
current = psf_ftell (psf) ;
if (calc_length)
{ psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->dataend)
psf->datalength -= psf->filelength - psf->dataend ;
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
} ;
encoding = au_format_to_encoding (psf->sf.format & SF_FORMAT_SUBMASK) ;
if (! encoding)
return (psf->error = SFE_BAD_OPEN_FORMAT) ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
/*
** Only attempt to seek if we are not writng to a pipe. If we are
** writing to a pipe we shouldn't be here anyway.
*/
if (psf->is_pipe == SF_FALSE)
psf_fseek (psf, 0, SEEK_SET) ;
/*
** AU format files allow a datalength value of -1 if the datalength
** is not know at the time the header is written.
** Also use this value of -1 if the datalength > 2 gigabytes.
*/
if (psf->datalength < 0 || psf->datalength > 0x7FFFFFFF)
datalength = -1 ;
else
datalength = (int) (psf->datalength & 0x7FFFFFFF) ;
if (psf->endian == SF_ENDIAN_BIG)
{ psf_binheader_writef (psf, "Em4", DOTSND_MARKER, AU_DATA_OFFSET) ;
psf_binheader_writef (psf, "E4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ;
}
else if (psf->endian == SF_ENDIAN_LITTLE)
{ psf_binheader_writef (psf, "em4", DNSDOT_MARKER, AU_DATA_OFFSET) ;
psf_binheader_writef (psf, "e4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ;
}
else
return (psf->error = SFE_BAD_OPEN_FORMAT) ;
/* Header construction complete so write it out. */
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* au_write_header */
static int
au_format_to_encoding (int format)
{
switch (format)
{ case SF_FORMAT_PCM_S8 : return AU_ENCODING_PCM_8 ;
case SF_FORMAT_PCM_16 : return AU_ENCODING_PCM_16 ;
case SF_FORMAT_PCM_24 : return AU_ENCODING_PCM_24 ;
case SF_FORMAT_PCM_32 : return AU_ENCODING_PCM_32 ;
case SF_FORMAT_FLOAT : return AU_ENCODING_FLOAT ;
case SF_FORMAT_DOUBLE : return AU_ENCODING_DOUBLE ;
case SF_FORMAT_ULAW : return AU_ENCODING_ULAW_8 ;
case SF_FORMAT_ALAW : return AU_ENCODING_ALAW_8 ;
case SF_FORMAT_G721_32 : return AU_ENCODING_ADPCM_G721_32 ;
case SF_FORMAT_G723_24 : return AU_ENCODING_ADPCM_G723_24 ;
case SF_FORMAT_G723_40 : return AU_ENCODING_ADPCM_G723_40 ;
default : break ;
} ;
return 0 ;
} /* au_format_to_encoding */
static int
au_read_header (SF_PRIVATE *psf)
{ AU_FMT au_fmt ;
int marker, dword ;
memset (&au_fmt, 0, sizeof (au_fmt)) ;
psf_binheader_readf (psf, "pm", 0, &marker) ;
psf_log_printf (psf, "%M\n", marker) ;
if (marker == DOTSND_MARKER)
{ psf->endian = SF_ENDIAN_BIG ;
psf_binheader_readf (psf, "E44444", &(au_fmt.dataoffset), &(au_fmt.datasize),
&(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ;
}
else if (marker == DNSDOT_MARKER)
{ psf->endian = SF_ENDIAN_LITTLE ;
psf_binheader_readf (psf, "e44444", &(au_fmt.dataoffset), &(au_fmt.datasize),
&(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ;
}
else
return SFE_AU_NO_DOTSND ;
psf_log_printf (psf, " Data Offset : %d\n", au_fmt.dataoffset) ;
if (psf->fileoffset > 0 && au_fmt.datasize == -1)
{ psf_log_printf (psf, " Data Size : -1\n") ;
return SFE_AU_EMBED_BAD_LEN ;
} ;
if (psf->fileoffset > 0)
{ psf->filelength = au_fmt.dataoffset + au_fmt.datasize ;
psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ;
}
else if (au_fmt.datasize == -1 || au_fmt.dataoffset + au_fmt.datasize == psf->filelength)
psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ;
else if (au_fmt.dataoffset + au_fmt.datasize < psf->filelength)
{ psf->filelength = au_fmt.dataoffset + au_fmt.datasize ;
psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ;
}
else
{ dword = psf->filelength - au_fmt.dataoffset ;
psf_log_printf (psf, " Data Size : %d (should be %d)\n", au_fmt.datasize, dword) ;
au_fmt.datasize = dword ;
} ;
psf->dataoffset = au_fmt.dataoffset ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf_ftell (psf) < psf->dataoffset)
psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ;
psf->sf.samplerate = au_fmt.samplerate ;
psf->sf.channels = au_fmt.channels ;
/* Only fill in type major. */
if (psf->endian == SF_ENDIAN_BIG)
psf->sf.format = SF_FORMAT_AU ;
else if (psf->endian == SF_ENDIAN_LITTLE)
psf->sf.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU ;
psf_log_printf (psf, " Encoding : %d => ", au_fmt.encoding) ;
psf->sf.format = psf->sf.format & SF_FORMAT_ENDMASK ;
switch (au_fmt.encoding)
{ case AU_ENCODING_ULAW_8 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ULAW ;
psf->bytewidth = 1 ; /* Before decoding */
psf_log_printf (psf, "8-bit ISDN u-law\n") ;
break ;
case AU_ENCODING_PCM_8 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_S8 ;
psf->bytewidth = 1 ;
psf_log_printf (psf, "8-bit linear PCM\n") ;
break ;
case AU_ENCODING_PCM_16 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
psf_log_printf (psf, "16-bit linear PCM\n") ;
break ;
case AU_ENCODING_PCM_24 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_24 ;
psf->bytewidth = 3 ;
psf_log_printf (psf, "24-bit linear PCM\n") ;
break ;
case AU_ENCODING_PCM_32 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_32 ;
psf->bytewidth = 4 ;
psf_log_printf (psf, "32-bit linear PCM\n") ;
break ;
case AU_ENCODING_FLOAT :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_FLOAT ;
psf->bytewidth = 4 ;
psf_log_printf (psf, "32-bit float\n") ;
break ;
case AU_ENCODING_DOUBLE :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_DOUBLE ;
psf->bytewidth = 8 ;
psf_log_printf (psf, "64-bit double precision float\n") ;
break ;
case AU_ENCODING_ALAW_8 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ALAW ;
psf->bytewidth = 1 ; /* Before decoding */
psf_log_printf (psf, "8-bit ISDN A-law\n") ;
break ;
case AU_ENCODING_ADPCM_G721_32 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G721_32 ;
psf->bytewidth = 0 ;
psf_log_printf (psf, "G721 32kbs ADPCM\n") ;
break ;
case AU_ENCODING_ADPCM_G723_24 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_24 ;
psf->bytewidth = 0 ;
psf_log_printf (psf, "G723 24kbs ADPCM\n") ;
break ;
case AU_ENCODING_ADPCM_G723_40 :
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_40 ;
psf->bytewidth = 0 ;
psf_log_printf (psf, "G723 40kbs ADPCM\n") ;
break ;
case AU_ENCODING_ADPCM_G722 :
psf_log_printf (psf, "G722 64 kbs ADPCM (unsupported)\n") ;
break ;
case AU_ENCODING_NEXT :
psf_log_printf (psf, "Weird NeXT encoding format (unsupported)\n") ;
break ;
default :
psf_log_printf (psf, "Unknown!!\n") ;
break ;
} ;
psf_log_printf (psf, " Sample Rate : %d\n", au_fmt.samplerate) ;
psf_log_printf (psf, " Channels : %d\n", au_fmt.channels) ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
if (! psf->sf.frames && psf->blockwidth)
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
return 0 ;
} /* au_read_header */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 31f691b1-cde9-4ed2-9469-6bca60fb9cd0
*/

254
libs/libsndfile/src/avr.c Normal file
View File

@@ -0,0 +1,254 @@
/*
** Copyright (C) 2004-2006 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T'))
#define AVR_HDR_SIZE 128
#define SFE_AVR_X 666
/*
** From: hyc@hanauma.Jpl.Nasa.Gov (Howard Chu)
**
** A lot of PD software exists to play Mac .snd files on the ST. One other
** format that seems pretty popular (used by a number of commercial packages)
** is the AVR format (from Audio Visual Research). This format has a 128 byte
** header that looks like this (its actually packed, but thats not portable):
*/
typedef struct
{ int marker ; /* 2BIT */
char name [8] ; /* null-padded sample name */
short mono ; /* 0 = mono, 0xffff = stereo */
short rez ; /* 8 = 8 bit, 16 = 16 bit */
short sign ; /* 0 = unsigned, 0xffff = signed */
short loop ; /* 0 = no loop, 0xffff = looping sample */
short midi ; /* 0xffff = no MIDI note assigned, */
/* 0xffXX = single key note assignment */
/* 0xLLHH = key split, low/hi note */
int srate ; /* sample frequency in hertz */
int frames ; /* sample length in bytes or words (see rez) */
int lbeg ; /* offset to start of loop in bytes or words. */
/* set to zero if unused */
int lend ; /* offset to end of loop in bytes or words. */
/* set to sample length if unused */
short res1 ; /* Reserved, MIDI keyboard split */
short res2 ; /* Reserved, sample compression */
short res3 ; /* Reserved */
char ext [20] ; /* Additional filename space, used if (name[7] != 0) */
char user [64] ; /* User defined. Typically ASCII message */
} AVR_HEADER ;
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int avr_close (SF_PRIVATE *psf) ;
static int avr_read_header (SF_PRIVATE *psf) ;
static int avr_write_header (SF_PRIVATE *psf, int calc_length) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
avr_open (SF_PRIVATE *psf)
{ int error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = avr_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AVR)
return SFE_BAD_OPEN_FORMAT ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
psf->endian = SF_ENDIAN_BIG ;
if (avr_write_header (psf, SF_FALSE))
return psf->error ;
psf->write_header = avr_write_header ;
} ;
psf->container_close = avr_close ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
error = pcm_init (psf) ;
return error ;
} /* avr_open */
static int
avr_read_header (SF_PRIVATE *psf)
{ AVR_HEADER hdr ;
memset (&hdr, 0, sizeof (hdr)) ;
psf_binheader_readf (psf, "pmb", 0, &hdr.marker, &hdr.name, sizeof (hdr.name)) ;
psf_log_printf (psf, "%M\n", hdr.marker) ;
if (hdr.marker != TWOBIT_MARKER)
return SFE_AVR_X ;
psf_log_printf (psf, " Name : %s\n", hdr.name) ;
psf_binheader_readf (psf, "E22222", &hdr.mono, &hdr.rez, &hdr.sign, &hdr.loop, &hdr.midi) ;
psf->sf.channels = (hdr.mono & 1) + 1 ;
psf_log_printf (psf, " Channels : %d\n Bit width : %d\n Signed : %s\n",
(hdr.mono & 1) + 1, hdr.rez, hdr.sign ? "yes" : "no") ;
switch ((hdr.rez << 16) + (hdr.sign & 1))
{ case ((8 << 16) + 0) :
psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_U8 ;
psf->bytewidth = 1 ;
break ;
case ((8 << 16) + 1) :
psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_S8 ;
psf->bytewidth = 1 ;
break ;
case ((16 << 16) + 1) :
psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
break ;
default :
psf_log_printf (psf, "Error : bad rez/sign combination.\n") ;
return SFE_AVR_X ;
} ;
psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ;
psf->sf.frames = hdr.frames ;
psf->sf.samplerate = hdr.srate ;
psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ;
psf_binheader_readf (psf, "E222", &hdr.res1, &hdr.res2, &hdr.res3) ;
psf_binheader_readf (psf, "bb", hdr.ext, sizeof (hdr.ext), hdr.user, sizeof (hdr.user)) ;
psf_log_printf (psf, " Ext : %s\n User : %s\n", hdr.ext, hdr.user) ;
psf->endian = SF_ENDIAN_BIG ;
psf->dataoffset = AVR_HDR_SIZE ;
psf->datalength = hdr.frames * (hdr.rez / 8) ;
if (psf->fileoffset > 0)
psf->filelength = AVR_HDR_SIZE + psf->datalength ;
if (psf_ftell (psf) != psf->dataoffset)
psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
if (psf->sf.frames == 0 && psf->blockwidth)
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
return 0 ;
} /* avr_read_header */
static int
avr_write_header (SF_PRIVATE *psf, int calc_length)
{ sf_count_t current ;
int sign ;
if (psf->pipeoffset > 0)
return 0 ;
current = psf_ftell (psf) ;
if (calc_length)
{ psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->dataend)
psf->datalength -= psf->filelength - psf->dataend ;
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
} ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
/*
** Only attempt to seek if we are not writng to a pipe. If we are
** writing to a pipe we shouldn't be here anyway.
*/
if (psf->is_pipe == SF_FALSE)
psf_fseek (psf, 0, SEEK_SET) ;
psf_binheader_writef (psf, "Emz22", TWOBIT_MARKER, make_size_t (8),
psf->sf.channels == 2 ? 0xFFFF : 0, psf->bytewidth * 8) ;
sign = ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_U8) ? 0 : 0xFFFF ;
psf_binheader_writef (psf, "E222", sign, 0, 0xFFFF) ;
psf_binheader_writef (psf, "E4444", psf->sf.samplerate, psf->sf.frames, 0, 0) ;
psf_binheader_writef (psf, "E222zz", 0, 0, 0, make_size_t (20), make_size_t (64)) ;
/* Header construction complete so write it out. */
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* avr_write_header */
static int
avr_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
avr_write_header (psf, SF_TRUE) ;
return 0 ;
} /* avr_close */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 0823d454-f39a-4a28-a776-607f1ef33b52
*/

View File

@@ -0,0 +1,89 @@
/*
** Copyright (C) 2006 Paul Davis <paul@linuxaudiosystems.com>
** Copyright (C) 2006 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <string.h>
#include "common.h"
/*
** Allocate and initialize a broadcast info structure.
*/
SF_BROADCAST_INFO*
broadcast_info_alloc (void)
{ SF_BROADCAST_INFO* bext ;
if ((bext = calloc (1, sizeof (SF_BROADCAST_INFO))) == NULL)
return NULL ;
return bext ;
} /* broadcast_info_alloc */
int
broadcast_info_copy (SF_BROADCAST_INFO* dst, SF_BROADCAST_INFO* src)
{ memcpy (dst, src, sizeof (SF_BROADCAST_INFO)) ;
/* Currently writing this version. */
dst->version = 1 ;
return SF_TRUE ;
} /* broadcast_info_copy */
int
broadcast_add_coding_history (SF_BROADCAST_INFO* bext, unsigned int channels, unsigned int samplerate)
{ char chnstr [16] ;
int count ;
switch (channels)
{ case 0 :
return SF_FALSE ;
case 1 :
strncpy (chnstr, "mono", sizeof (chnstr)) ;
break ;
case 2 :
strncpy (chnstr, "stereo", sizeof (chnstr)) ;
break ;
default :
LSF_SNPRINTF (chnstr, sizeof (chnstr), "%uchn", channels) ;
break ;
}
count = LSF_SNPRINTF (bext->coding_history, sizeof (bext->coding_history), "F=%u,A=PCM,M=%s,W=24,T=%s-%s", samplerate, chnstr, PACKAGE, VERSION) ;
if (count >= SIGNED_SIZEOF (bext->coding_history))
bext->coding_history_size = sizeof (bext->coding_history) ;
else
{ count += count & 1 ;
bext->coding_history_size = count ;
} ;
return SF_TRUE ;
} /* broadcast_add_coding_history */
/*
** Do not edit or modify anything in this comment block.
** The following line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 4b3b69c7-d710-4424-9da0-5048534a0beb
*/

538
libs/libsndfile/src/caf.c Normal file
View File

@@ -0,0 +1,538 @@
/*
** Copyright (C) 2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define aac_MARKER MAKE_MARKER ('a', 'a', 'c', ' ')
#define alac_MARKER MAKE_MARKER ('a', 'l', 'a', 'c')
#define alaw_MARKER MAKE_MARKER ('a', 'l', 'a', 'w')
#define caff_MARKER MAKE_MARKER ('c', 'a', 'f', 'f')
#define chan_MARKER MAKE_MARKER ('c', 'h', 'a', 'n')
#define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a')
#define desc_MARKER MAKE_MARKER ('d', 'e', 's', 'c')
#define edct_MARKER MAKE_MARKER ('e', 'd', 'c', 't')
#define free_MARKER MAKE_MARKER ('f', 'r', 'e', 'e')
#define ima4_MARKER MAKE_MARKER ('i', 'm', 'a', '4')
#define info_MARKER MAKE_MARKER ('i', 'n', 'f', 'o')
#define inst_MARKER MAKE_MARKER ('i', 'n', 's', 't')
#define kuki_MARKER MAKE_MARKER ('k', 'u', 'k', 'i')
#define lpcm_MARKER MAKE_MARKER ('l', 'p', 'c', 'm')
#define mark_MARKER MAKE_MARKER ('m', 'a', 'r', 'k')
#define midi_MARKER MAKE_MARKER ('m', 'i', 'd', 'i')
#define mp1_MARKER MAKE_MARKER ('.', 'm', 'p', '1')
#define mp2_MARKER MAKE_MARKER ('.', 'm', 'p', '2')
#define mp3_MARKER MAKE_MARKER ('.', 'm', 'p', '3')
#define ovvw_MARKER MAKE_MARKER ('o', 'v', 'v', 'w')
#define pakt_MARKER MAKE_MARKER ('p', 'a', 'k', 't')
#define peak_MARKER MAKE_MARKER ('p', 'e', 'a', 'k')
#define regn_MARKER MAKE_MARKER ('r', 'e', 'g', 'n')
#define strg_MARKER MAKE_MARKER ('s', 't', 'r', 'g')
#define umid_MARKER MAKE_MARKER ('u', 'm', 'i', 'd')
#define uuid_MARKER MAKE_MARKER ('u', 'u', 'i', 'd')
#define ulaw_MARKER MAKE_MARKER ('u', 'l', 'a', 'w')
#define MAC3_MARKER MAKE_MARKER ('M', 'A', 'C', '3')
#define MAC6_MARKER MAKE_MARKER ('M', 'A', 'C', '6')
#define CAF_PEAK_CHUNK_SIZE(ch) (sizeof (int) + ch * (sizeof (float) + 8))
#define SFE_CAF_NOT_CAF 666
#define SFE_CAF_NO_DESC 667
#define SFE_CAF_BAD_PEAK 668
/*------------------------------------------------------------------------------
** Typedefs.
*/
typedef struct
{ unsigned char srate [8] ;
unsigned int fmt_id ;
unsigned int fmt_flags ;
unsigned int pkt_bytes ;
unsigned int pkt_frames ;
unsigned int channels_per_frame ;
unsigned int bits_per_chan ;
} DESC_CHUNK ;
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int caf_close (SF_PRIVATE *psf) ;
static int caf_read_header (SF_PRIVATE *psf) ;
static int caf_write_header (SF_PRIVATE *psf, int calc_length) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
caf_open (SF_PRIVATE *psf)
{ int subformat, format, error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = caf_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
format = psf->sf.format & SF_FORMAT_TYPEMASK ;
if (format != SF_FORMAT_CAF)
return SFE_BAD_OPEN_FORMAT ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
if (psf->mode != SFM_RDWR || psf->filelength < 44)
{ psf->filelength = 0 ;
psf->datalength = 0 ;
psf->dataoffset = 0 ;
psf->sf.frames = 0 ;
} ;
psf->str_flags = SF_STR_ALLOW_START ;
/*
** By default, add the peak chunk to floating point files. Default behaviour
** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
*/
if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
{ if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
return SFE_MALLOC_FAILED ;
psf->peak_info->peak_loc = SF_PEAK_START ;
} ;
if ((error = caf_write_header (psf, SF_FALSE)) != 0)
return error ;
psf->write_header = caf_write_header ;
} ;
psf->container_close = caf_close ;
/*psf->command = caf_command ;*/
switch (subformat)
{ case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_PCM_32 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_ULAW :
error = ulaw_init (psf) ;
break ;
case SF_FORMAT_ALAW :
error = alaw_init (psf) ;
break ;
/* Lite remove start */
case SF_FORMAT_FLOAT :
error = float32_init (psf) ;
break ;
case SF_FORMAT_DOUBLE :
error = double64_init (psf) ;
break ;
/* Lite remove end */
default :
return SFE_UNSUPPORTED_ENCODING ;
} ;
return error ;
} /* caf_open */
static int
caf_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
caf_write_header (psf, SF_TRUE) ;
return 0 ;
} /* caf_close */
/*------------------------------------------------------------------------------
*/
static int
decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc)
{ int format ;
psf->sf.channels = desc->channels_per_frame ;
format = SF_FORMAT_CAF | (psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0) ;
if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1)
{ /* Floating point data. */
if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
{ psf->bytewidth = 4 ;
return format | SF_FORMAT_FLOAT ;
} ;
if (desc->bits_per_chan == 64 && desc->pkt_bytes == 8 * desc->channels_per_frame)
{ psf->bytewidth = 8 ;
return format | SF_FORMAT_DOUBLE ;
} ;
} ;
if ((desc->fmt_flags & 1) != 0)
{ psf_log_printf (psf, "**** Ooops, 'desc' chunk suggests float data, but other info invalid.\n") ;
return 0 ;
} ;
if (desc->fmt_id == lpcm_MARKER)
{ /* Integer data. */
if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
{ psf->bytewidth = 4 ;
return format | SF_FORMAT_PCM_32 ;
} ;
if (desc->bits_per_chan == 24 && desc->pkt_bytes == 3 * desc->channels_per_frame)
{ psf->bytewidth = 3 ;
return format | SF_FORMAT_PCM_24 ;
} ;
if (desc->bits_per_chan == 16 && desc->pkt_bytes == 2 * desc->channels_per_frame)
{ psf->bytewidth = 2 ;
return format | SF_FORMAT_PCM_16 ;
} ;
if (desc->bits_per_chan == 8 && desc->pkt_bytes == 1 * desc->channels_per_frame)
{ psf->bytewidth = 1 ;
return format | SF_FORMAT_PCM_S8 ;
} ;
} ;
if (desc->fmt_id == alaw_MARKER && desc->bits_per_chan == 8)
{ psf->bytewidth = 1 ;
return format | SF_FORMAT_ALAW ;
} ;
if (desc->fmt_id == ulaw_MARKER && desc->bits_per_chan == 8)
{ psf->bytewidth = 1 ;
return format | SF_FORMAT_ULAW ;
} ;
return 0 ;
} /* decode_desc_chunk */
static int
caf_read_header (SF_PRIVATE *psf)
{ DESC_CHUNK desc ;
sf_count_t chunk_size ;
double srate ;
short version, flags ;
int marker, k, have_data = 0 ;
memset (&desc, 0, sizeof (desc)) ;
/* Set position to start of file to begin reading header. */
psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ;
psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ;
if (marker != caff_MARKER)
return SFE_CAF_NOT_CAF ;
psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, psf->u.ucbuf, 8) ;
srate = double64_be_read (psf->u.ucbuf) ;
LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), "%5.3f", srate) ;
psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, psf->u.cbuf) ;
if (marker != desc_MARKER)
return SFE_CAF_NO_DESC ;
if (chunk_size < sizeof (DESC_CHUNK))
{ psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ;
return SFE_MALFORMED_FILE ;
} ;
psf->sf.samplerate = lrint (srate) ;
psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.pkt_frames,
&desc.channels_per_frame, &desc.bits_per_chan) ;
psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n"
" Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n",
desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
if (chunk_size > sizeof (DESC_CHUNK))
psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ;
psf->sf.channels = desc.channels_per_frame ;
while (have_data == 0 && psf_ftell (psf) < psf->filelength - SIGNED_SIZEOF (marker))
{ psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ;
switch (marker)
{ case peak_MARKER :
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels))
{ psf_binheader_readf (psf, "j", (int) chunk_size) ;
psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
return SFE_CAF_BAD_PEAK ;
} ;
if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
return SFE_MALLOC_FAILED ;
/* read in rest of PEAK chunk. */
psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ;
psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ;
psf_log_printf (psf, " Ch Position Value\n") ;
for (k = 0 ; k < psf->sf.channels ; k++)
{ sf_count_t position ;
float value ;
psf_binheader_readf (psf, "Ef8", &value, &position) ;
psf->peak_info->peaks [k].value = value ;
psf->peak_info->peaks [k].position = position ;
LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %-12ld %g\n", k, (long) position, value) ;
psf_log_printf (psf, psf->u.cbuf) ;
} ;
psf->peak_info->peak_loc = SF_PEAK_START ;
break ;
case free_MARKER :
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
psf_binheader_readf (psf, "j", (int) chunk_size) ;
break ;
case data_MARKER :
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
psf_binheader_readf (psf, "E4", &k) ;
psf_log_printf (psf, " edit : %u\n", k) ;
have_data = 1 ;
break ;
default :
psf_log_printf (psf, " %M : %D (skipped)\n", marker, chunk_size) ;
psf_binheader_readf (psf, "j", (int) chunk_size) ;
break ;
} ;
} ;
if (have_data == 0)
{ psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ;
return SFE_MALFORMED_FILE ;
} ;
psf_log_printf (psf, "End\n") ;
psf->dataoffset = psf_ftell (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0)
return SFE_UNSUPPORTED_ENCODING ;
if (psf->bytewidth > 0)
psf->sf.frames = psf->datalength / psf->bytewidth ;
return 0 ;
} /* caf_read_header */
/*------------------------------------------------------------------------------
*/
static int
caf_write_header (SF_PRIVATE *psf, int calc_length)
{ DESC_CHUNK desc ;
sf_count_t current, free_len ;
int subformat ;
memset (&desc, 0, sizeof (desc)) ;
current = psf_ftell (psf) ;
if (calc_length)
{ psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->dataend)
psf->datalength -= psf->filelength - psf->dataend ;
if (psf->bytewidth > 0)
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
} ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
psf_fseek (psf, 0, SEEK_SET) ;
/* 'caff' marker, version and flags. */
psf_binheader_writef (psf, "Em22", caff_MARKER, 1, 0) ;
/* 'desc' marker and chunk size. */
psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ;
double64_be_write (1.0 * psf->sf.samplerate, psf->u.ucbuf) ;
psf_binheader_writef (psf, "b", psf->u.ucbuf, 8) ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
psf->endian = SF_ENDIAN_BIG ;
else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU))
psf->endian = SF_ENDIAN_LITTLE ;
if (psf->endian == SF_ENDIAN_LITTLE)
desc.fmt_flags = 2 ;
else
psf->endian = SF_ENDIAN_BIG ;
/* initial section (same for all, it appears) */
switch (subformat)
{ case SF_FORMAT_PCM_S8 :
desc.fmt_id = lpcm_MARKER ;
psf->bytewidth = 1 ;
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
desc.pkt_frames = 1 ;
desc.channels_per_frame = psf->sf.channels ;
desc.bits_per_chan = 8 ;
break ;
case SF_FORMAT_PCM_16 :
desc.fmt_id = lpcm_MARKER ;
psf->bytewidth = 2 ;
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
desc.pkt_frames = 1 ;
desc.channels_per_frame = psf->sf.channels ;
desc.bits_per_chan = 16 ;
break ;
case SF_FORMAT_PCM_24 :
psf->bytewidth = 3 ;
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
desc.pkt_frames = 1 ;
desc.channels_per_frame = psf->sf.channels ;
desc.bits_per_chan = 24 ;
desc.fmt_id = lpcm_MARKER ;
break ;
case SF_FORMAT_PCM_32 :
desc.fmt_id = lpcm_MARKER ;
psf->bytewidth = 4 ;
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
desc.pkt_frames = 1 ;
desc.channels_per_frame = psf->sf.channels ;
desc.bits_per_chan = 32 ;
break ;
case SF_FORMAT_FLOAT :
desc.fmt_id = lpcm_MARKER ;
desc.fmt_flags |= 1 ;
psf->bytewidth = 4 ;
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
desc.pkt_frames = 1 ;
desc.channels_per_frame = psf->sf.channels ;
desc.bits_per_chan = 32 ;
break ;
case SF_FORMAT_DOUBLE :
desc.fmt_id = lpcm_MARKER ;
desc.fmt_flags |= 1 ;
psf->bytewidth = 8 ;
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
desc.pkt_frames = 1 ;
desc.channels_per_frame = psf->sf.channels ;
desc.bits_per_chan = 64 ;
break ;
case SF_FORMAT_ALAW :
desc.fmt_id = alaw_MARKER ;
psf->bytewidth = 1 ;
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
desc.pkt_frames = 1 ;
desc.channels_per_frame = psf->sf.channels ;
desc.bits_per_chan = 8 ;
break ;
case SF_FORMAT_ULAW :
desc.fmt_id = ulaw_MARKER ;
psf->bytewidth = 1 ;
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
desc.pkt_frames = 1 ;
desc.channels_per_frame = psf->sf.channels ;
desc.bits_per_chan = 8 ;
break ;
default :
return SFE_UNIMPLEMENTED ;
} ;
psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
#if 0
if (psf->str_flags & SF_STR_LOCATE_START)
caf_write_strings (psf, SF_STR_LOCATE_START) ;
#endif
if (psf->peak_info != NULL)
{ int k ;
psf_binheader_writef (psf, "Em84", peak_MARKER, (sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels), psf->peak_info->edit_number) ;
for (k = 0 ; k < psf->sf.channels ; k++)
psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
} ;
/* Add free chunk so that the actual audio data starts at a multiple 0x1000. */
free_len = 0x1000 - psf->headindex - 16 - 12 ;
while (free_len < 0)
free_len += 0x1000 ;
psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ;
psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength, 0) ;
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
if (current < psf->dataoffset)
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
else if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* caf_write_header */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 65883e65-bd3c-4618-9241-d3c02fd630bd
*/

View File

@@ -0,0 +1,367 @@
/*
** Copyright (C) 2001-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "sndfile.h"
#include "common.h"
static SF_FORMAT_INFO const simple_formats [] =
{
{ SF_FORMAT_AIFF | SF_FORMAT_PCM_16,
"AIFF (Apple/SGI 16 bit PCM)", "aiff"
},
{ SF_FORMAT_AIFF | SF_FORMAT_FLOAT,
"AIFF (Apple/SGI 32 bit float)", "aifc"
},
{ SF_FORMAT_AIFF | SF_FORMAT_PCM_S8,
"AIFF (Apple/SGI 8 bit PCM)", "aiff"
},
{ SF_FORMAT_AU | SF_FORMAT_PCM_16,
"AU (Sun/Next 16 bit PCM)", "au"
},
{ SF_FORMAT_AU | SF_FORMAT_ULAW,
"AU (Sun/Next 8-bit u-law)", "au"
},
{ SF_FORMAT_CAF | SF_FORMAT_PCM_16,
"CAF (Apple 16 bit PCM)", "caf"
},
#ifdef HAVE_FLAC_ALL_H
{ SF_FORMAT_FLAC | SF_FORMAT_PCM_16,
"FLAC 16 bit", "flac"
},
#endif
{ SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM,
"OKI Dialogic VOX ADPCM", "vox"
},
{ SF_FORMAT_WAV | SF_FORMAT_PCM_16,
"WAV (Microsoft 16 bit PCM)", "wav"
},
{ SF_FORMAT_WAV | SF_FORMAT_FLOAT,
"WAV (Microsoft 32 bit float)", "wav"
},
{ SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM,
"WAV (Microsoft 4 bit IMA ADPCM)", "wav"
},
{ SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM,
"WAV (Microsoft 4 bit MS ADPCM)", "wav"
},
{ SF_FORMAT_WAV | SF_FORMAT_PCM_U8,
"WAV (Microsoft 8 bit PCM)", "wav"
},
} ; /* simple_formats */
int
psf_get_format_simple_count (void)
{ return (sizeof (simple_formats) / sizeof (SF_FORMAT_INFO)) ;
} /* psf_get_format_simple_count */
int
psf_get_format_simple (SF_FORMAT_INFO *data)
{ int indx ;
if (data->format < 0 || data->format >= (SIGNED_SIZEOF (simple_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
return SFE_BAD_CONTROL_CMD ;
indx = data->format ;
memcpy (data, &(simple_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ;
return 0 ;
} /* psf_get_format_simple */
/*============================================================================
** Major format info.
*/
static SF_FORMAT_INFO const major_formats [] =
{
{ SF_FORMAT_AIFF, "AIFF (Apple/SGI)", "aiff" },
{ SF_FORMAT_AU, "AU (Sun/NeXT)", "au" },
{ SF_FORMAT_AVR, "AVR (Audio Visual Research)", "avr" },
{ SF_FORMAT_CAF, "CAF (Apple Core Audio File)", "caf" },
#ifdef HAVE_FLAC_ALL_H
{ SF_FORMAT_FLAC, "FLAC (FLAC Lossless Audio Codec)", "flac" },
#endif
{ SF_FORMAT_HTK, "HTK (HMM Tool Kit)", "htk" },
{ SF_FORMAT_SVX, "IFF (Amiga IFF/SVX8/SV16)", "iff" },
{ SF_FORMAT_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" },
{ SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" },
{ SF_FORMAT_PAF, "PAF (Ensoniq PARIS)", "paf" },
{ SF_FORMAT_PVF, "PVF (Portable Voice Format)", "pvf" },
{ SF_FORMAT_RAW, "RAW (header-less)", "raw" },
{ SF_FORMAT_SD2, "SD2 (Sound Designer II)", "sd2" },
{ SF_FORMAT_SDS, "SDS (Midi Sample Dump Standard)", "sds" },
{ SF_FORMAT_IRCAM, "SF (Berkeley/IRCAM/CARL)", "sf" },
{ SF_FORMAT_VOC, "VOC (Creative Labs)", "voc" },
{ SF_FORMAT_W64, "W64 (SoundFoundry WAVE 64)", "w64" },
{ SF_FORMAT_WAV, "WAV (Microsoft)", "wav" },
{ SF_FORMAT_NIST, "WAV (NIST Sphere)", "wav" },
{ SF_FORMAT_WAVEX, "WAVEX (Microsoft)", "wav" },
{ SF_FORMAT_XI, "XI (FastTracker 2)", "xi" },
} ; /* major_formats */
int
psf_get_format_major_count (void)
{ return (sizeof (major_formats) / sizeof (SF_FORMAT_INFO)) ;
} /* psf_get_format_major_count */
int
psf_get_format_major (SF_FORMAT_INFO *data)
{ int indx ;
if (data->format < 0 || data->format >= (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
return SFE_BAD_CONTROL_CMD ;
indx = data->format ;
memcpy (data, &(major_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ;
return 0 ;
} /* psf_get_format_major */
/*============================================================================
** Subtype format info.
*/
static SF_FORMAT_INFO subtype_formats [] =
{
{ SF_FORMAT_PCM_S8, "Signed 8 bit PCM", NULL },
{ SF_FORMAT_PCM_16, "Signed 16 bit PCM", NULL },
{ SF_FORMAT_PCM_24, "Signed 24 bit PCM", NULL },
{ SF_FORMAT_PCM_32, "Signed 32 bit PCM", NULL },
{ SF_FORMAT_PCM_U8, "Unsigned 8 bit PCM", NULL },
{ SF_FORMAT_FLOAT, "32 bit float", NULL },
{ SF_FORMAT_DOUBLE, "64 bit float", NULL },
{ SF_FORMAT_ULAW, "U-Law", NULL },
{ SF_FORMAT_ALAW, "A-Law", NULL },
{ SF_FORMAT_IMA_ADPCM, "IMA ADPCM", NULL },
{ SF_FORMAT_MS_ADPCM, "Microsoft ADPCM", NULL },
{ SF_FORMAT_GSM610, "GSM 6.10", NULL },
{ SF_FORMAT_G721_32, "32kbs G721 ADPCM", NULL },
{ SF_FORMAT_G723_24, "24kbs G723 ADPCM", NULL },
{ SF_FORMAT_DWVW_12, "12 bit DWVW", NULL },
{ SF_FORMAT_DWVW_16, "16 bit DWVW", NULL },
{ SF_FORMAT_DWVW_24, "24 bit DWVW", NULL },
{ SF_FORMAT_VOX_ADPCM, "VOX ADPCM", "vox" },
{ SF_FORMAT_DPCM_16, "16 bit DPCM", NULL },
{ SF_FORMAT_DPCM_8, "8 bit DPCM", NULL }
} ; /* subtype_formats */
int
psf_get_format_subtype_count (void)
{ return (sizeof (subtype_formats) / sizeof (SF_FORMAT_INFO)) ;
} /* psf_get_format_subtype_count */
int
psf_get_format_subtype (SF_FORMAT_INFO *data)
{ int indx ;
if (data->format < 0 || data->format >= (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
return SFE_BAD_CONTROL_CMD ;
indx = data->format ;
memcpy (data, &(subtype_formats [indx]), sizeof (SF_FORMAT_INFO)) ;
return 0 ;
} /* psf_get_format_subtype */
/*==============================================================================
*/
int
psf_get_format_info (SF_FORMAT_INFO *data)
{ int k, format ;
if (data->format & SF_FORMAT_TYPEMASK)
{ format = data->format & SF_FORMAT_TYPEMASK ;
for (k = 0 ; k < (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++)
{ if (format == major_formats [k].format)
{ memcpy (data, &(major_formats [k]), sizeof (SF_FORMAT_INFO)) ;
return 0 ;
} ;
} ;
}
else if (data->format & SF_FORMAT_SUBMASK)
{ format = data->format & SF_FORMAT_SUBMASK ;
for (k = 0 ; k < (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++)
{ if (format == subtype_formats [k].format)
{ memcpy (data, &(subtype_formats [k]), sizeof (SF_FORMAT_INFO)) ;
return 0 ;
} ;
} ;
} ;
memset (data, 0, sizeof (SF_FORMAT_INFO)) ;
return SFE_BAD_CONTROL_CMD ;
} /* psf_get_format_info */
/*==============================================================================
*/
double
psf_calc_signal_max (SF_PRIVATE *psf, int normalize)
{ sf_count_t position ;
double max_val, temp, *data ;
int k, len, readcount, save_state ;
/* If the file is not seekable, there is nothing we can do. */
if (! psf->sf.seekable)
{ psf->error = SFE_NOT_SEEKABLE ;
return 0.0 ;
} ;
if (! psf->read_double)
{ psf->error = SFE_UNIMPLEMENTED ;
return 0.0 ;
} ;
save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ;
sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ;
/* Brute force. Read the whole file and find the biggest sample. */
/* Get current position in file */
position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ;
/* Go to start of file. */
sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ;
data = psf->u.dbuf ;
len = ARRAY_LEN (psf->u.dbuf) ;
for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */)
{ readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
for (k = 0 ; k < readcount ; k++)
{ temp = fabs (data [k]) ;
max_val = temp > max_val ? temp : max_val ;
} ;
} ;
/* Return to SNDFILE to original state. */
sf_seek ((SNDFILE*) psf, position, SEEK_SET) ;
sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ;
return max_val ;
} /* psf_calc_signal_max */
int
psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize)
{ sf_count_t position ;
double temp, *data ;
int k, len, readcount, save_state ;
int chan ;
/* If the file is not seekable, there is nothing we can do. */
if (! psf->sf.seekable)
return (psf->error = SFE_NOT_SEEKABLE) ;
if (! psf->read_double)
return (psf->error = SFE_UNIMPLEMENTED) ;
save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ;
sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ;
memset (peaks, 0, sizeof (double) * psf->sf.channels) ;
/* Brute force. Read the whole file and find the biggest sample for each channel. */
position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ; /* Get current position in file */
sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ; /* Go to start of file. */
len = ARRAY_LEN (psf->u.dbuf) ;
data = psf->u.dbuf ;
chan = 0 ;
readcount = len ;
while (readcount > 0)
{ readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
for (k = 0 ; k < readcount ; k++)
{ temp = fabs (data [k]) ;
peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ;
chan = (chan + 1) % psf->sf.channels ;
} ;
} ;
sf_seek ((SNDFILE*) psf, position, SEEK_SET) ; /* Return to original position. */
sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ;
return 0 ;
} /* psf_calc_max_all_channels */
int
psf_get_signal_max (SF_PRIVATE *psf, double *peak)
{ int k ;
if (psf->peak_info == NULL)
return SF_FALSE ;
peak [0] = psf->peak_info->peaks [0].value ;
for (k = 1 ; k < psf->sf.channels ; k++)
peak [0] = SF_MAX (peak [0], psf->peak_info->peaks [k].value) ;
return SF_TRUE ;
} /* psf_get_signal_max */
int
psf_get_max_all_channels (SF_PRIVATE *psf, double *peaks)
{ int k ;
if (psf->peak_info == NULL)
return SF_FALSE ;
for (k = 0 ; k < psf->sf.channels ; k++)
peaks [k] = psf->peak_info->peaks [k].value ;
return SF_TRUE ;
} /* psf_get_max_all_channels */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 0aae0d9d-ab2b-4d70-ade3-47a534666f8e
*/

1290
libs/libsndfile/src/common.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,766 @@
/*
** Copyright (C) 1999-2006 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SNDFILE_COMMON_H
#define SNDFILE_COMMON_H
#include "sfconfig.h"
#include <stdlib.h>
#if HAVE_STDINT_H
#include <stdint.h>
#endif
#ifndef SNDFILE_H
#include "sndfile.h"
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#ifdef __cplusplus
#error "This code is not designed to be compiled with a C++ compiler."
#endif
#ifdef UNUSED
#elif defined (__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
#elif defined (__LCLINT__)
# define UNUSED(x) /*@unused@*/ x
#else
# define UNUSED(x) x
#endif
#ifdef __GNUC__
# define WARN_UNUSED __attribute__ ((warn_unused_result))
#else
# define WARN_UNUSED
#endif
#define SF_BUFFER_LEN (8192*2)
#define SF_FILENAME_LEN (512)
#define SF_SYSERR_LEN (256)
#define SF_MAX_STRINGS (16)
#define SF_STR_BUFFER_LEN (8192)
#define SF_HEADER_LEN (4100 + SF_STR_BUFFER_LEN)
#define PSF_SEEK_ERROR ((sf_count_t) -1)
#define BITWIDTH2BYTES(x) (((x) + 7) / 8)
/* For some reason sizeof returns an unsigned value which causes
** a warning when that value is added or subtracted from a signed
** value. Use SIGNED_SIZEOF instead.
*/
#define SIGNED_SIZEOF(x) ((int) sizeof (x))
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
#define SF_MAX(a,b) ((a) > (b) ? (a) : (b))
#define SF_MIN(a,b) ((a) < (b) ? (a) : (b))
enum
{ /* PEAK chunk location. */
SF_PEAK_START = 42,
SF_PEAK_END = 43,
/* PEAK chunk location. */
SF_SCALE_MAX = 52,
SF_SCALE_MIN = 53,
/* str_flags values. */
SF_STR_ALLOW_START = 0x0100,
SF_STR_ALLOW_END = 0x0200,
/* Location of strings. */
SF_STR_LOCATE_START = 0x0400,
SF_STR_LOCATE_END = 0x0800,
SFD_TYPEMASK = 0x0FFFFFFF
} ;
#define SFM_MASK (SFM_READ | SFM_WRITE | SFM_RDWR)
#define SFM_UNMASK (~SFM_MASK)
/*---------------------------------------------------------------------------------------
** Formats that may be supported at some time in the future.
** When support is finalised, these values move to src/sndfile.h.
*/
enum
{ /* Work in progress. */
/* Formats supported read only. */
SF_FORMAT_WVE = 0x4020000, /* Psion ALaw Sound File */
SF_FORMAT_TXW = 0x4030000, /* Yamaha TX16 sampler file */
SF_FORMAT_DWD = 0x4040000, /* DiamondWare Digirized */
/* Following are detected but not supported. */
SF_FORMAT_OGG = 0x4090000,
SF_FORMAT_REX = 0x40A0000, /* Propellorheads Rex/Rcy */
SF_FORMAT_REX2 = 0x40D0000, /* Propellorheads Rex2 */
SF_FORMAT_KRZ = 0x40E0000, /* Kurzweil sampler file */
SF_FORMAT_WMA = 0x4100000, /* Windows Media Audio. */
SF_FORMAT_SHN = 0x4110000, /* Shorten. */
/* Unsupported encodings. */
SF_FORMAT_VORBIS = 0x1001,
SF_FORMAT_SVX_FIB = 0x1020, /* SVX Fibonacci Delta encoding. */
SF_FORMAT_SVX_EXP = 0x1021, /* SVX Exponential Delta encoding. */
SF_FORMAT_PCM_N = 0x1030
} ;
/*---------------------------------------------------------------------------------------
** PEAK_CHUNK - This chunk type is common to both AIFF and WAVE files although their
** endian encodings are different.
*/
typedef struct
{ double value ; /* signed value of peak */
sf_count_t position ; /* the sample frame for the peak */
} PEAK_POS ;
typedef struct
{ /* libsndfile internal : write a PEAK chunk at the start or end of the file? */
int peak_loc ;
/* WAV/AIFF */
unsigned int version ; /* version of the PEAK chunk */
unsigned int timestamp ; /* secs since 1/1/1970 */
/* CAF */
unsigned int edit_number ;
#if HAVE_FLEXIBLE_ARRAY
/* the per channel peak info */
PEAK_POS peaks [] ;
#else
/*
** This is not ISO compliant C. It works on some compilers which
** don't support the ISO standard flexible struct array which is
** used above. If your compiler doesn't like this I suggest you find
** youself a 1999 ISO C standards compilant compiler. GCC-3.X is
** highly recommended.
*/
PEAK_POS peaks [0] ;
#endif
} PEAK_INFO ;
static inline PEAK_INFO *
peak_info_calloc (int channels)
{ return calloc (1, sizeof (PEAK_INFO) + channels * sizeof (PEAK_POS)) ;
} /* peak_info_calloc */
typedef struct
{ int type ;
int flags ;
char *str ;
} STR_DATA ;
static inline size_t
make_size_t (int x)
{ return (size_t) x ;
} /* size_t_of_int */
/*=======================================================================================
** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the
** sf_open_XXXX functions. The caller however has no knowledge of the struct's
** contents.
*/
typedef struct sf_private_tag
{ /* Force the compiler to double align the start of buffer. */
union
{ double dbuf [SF_BUFFER_LEN / sizeof (double)] ;
#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
int64_t lbuf [SF_BUFFER_LEN / sizeof (int64_t)] ;
#else
long lbuf [SF_BUFFER_LEN / sizeof (double)] ;
#endif
float fbuf [SF_BUFFER_LEN / sizeof (float)] ;
int ibuf [SF_BUFFER_LEN / sizeof (int)] ;
short sbuf [SF_BUFFER_LEN / sizeof (short)] ;
char cbuf [SF_BUFFER_LEN / sizeof (char)] ;
signed char scbuf [SF_BUFFER_LEN / sizeof (signed char)] ;
unsigned char ucbuf [SF_BUFFER_LEN / sizeof (signed char)] ;
} u ;
char filepath [SF_FILENAME_LEN] ;
char rsrcpath [SF_FILENAME_LEN] ;
char directory [SF_FILENAME_LEN] ;
char filename [SF_FILENAME_LEN / 4] ;
char syserr [SF_SYSERR_LEN] ;
/* logbuffer and logindex should only be changed within the logging functions
** of common.c
*/
char logbuffer [SF_BUFFER_LEN] ;
unsigned char header [SF_HEADER_LEN] ; /* Must be unsigned */
int rwf_endian ; /* Header endian-ness flag. */
/* Storage and housekeeping data for adding/reading strings from
** sound files.
*/
STR_DATA strings [SF_MAX_STRINGS] ;
char str_storage [SF_STR_BUFFER_LEN] ;
char *str_end ;
int str_flags ;
/* Guard value. If this changes the buffers above have overflowed. */
int Magick ;
/* Index variables for maintaining logbuffer and header above. */
int logindex ;
int headindex, headend ;
int has_text ;
int do_not_close_descriptor ;
#if USE_WINDOWS_API
/*
** These fields can only be used in src/file_io.c.
** They are basically the same as a windows file HANDLE.
*/
void *hfile, *hrsrc, *hsaved ;
#else
/* These fields can only be used in src/file_io.c. */
int filedes, rsrcdes, savedes ;
#endif
int error ;
int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */
int endian ; /* File endianness : SF_ENDIAN_LITTLE or SF_ENDIAN_BIG. */
int float_endswap ; /* Need to endswap float32s? */
/*
** Maximum float value for calculating the multiplier for
** float/double to short/int conversions.
*/
int float_int_mult ;
float float_max ;
/* Vairables for handling pipes. */
int is_pipe ; /* True if file is a pipe. */
sf_count_t pipeoffset ; /* Number of bytes read from a pipe. */
/* True if clipping must be performed on float->int conversions. */
int add_clipping ;
SF_INFO sf ;
int have_written ; /* Has a single write been done to the file? */
PEAK_INFO *peak_info ;
/* Loop Info */
SF_LOOP_INFO *loop_info ;
SF_INSTRUMENT *instrument ;
/* Broadcast (EBU) Info */
SF_BROADCAST_INFO *broadcast_info ;
sf_count_t filelength ; /* Overall length of (embedded) file. */
sf_count_t fileoffset ; /* Offset in number of bytes from beginning of file. */
sf_count_t rsrclength ; /* Length of the resource fork (if it exists). */
sf_count_t dataoffset ; /* Offset in number of bytes from beginning of file. */
sf_count_t datalength ; /* Length in bytes of the audio data. */
sf_count_t dataend ; /* Offset to file tailer. */
int blockwidth ; /* Size in bytes of one set of interleaved samples. */
int bytewidth ; /* Size in bytes of one sample (one channel). */
void *dither ;
void *interleave ;
int last_op ; /* Last operation; either SFM_READ or SFM_WRITE */
sf_count_t read_current ;
sf_count_t write_current ;
void *fdata ; /* This is a pointer to dynamically allocated file format
** specific data.
*/
SF_DITHER_INFO write_dither ;
SF_DITHER_INFO read_dither ;
int norm_double ;
int norm_float ;
int auto_header ;
int ieee_replace ;
/* A set of file specific function pointers */
sf_count_t (*read_short) (struct sf_private_tag*, short *ptr, sf_count_t len) ;
sf_count_t (*read_int) (struct sf_private_tag*, int *ptr, sf_count_t len) ;
sf_count_t (*read_float) (struct sf_private_tag*, float *ptr, sf_count_t len) ;
sf_count_t (*read_double) (struct sf_private_tag*, double *ptr, sf_count_t len) ;
sf_count_t (*write_short) (struct sf_private_tag*, const short *ptr, sf_count_t len) ;
sf_count_t (*write_int) (struct sf_private_tag*, const int *ptr, sf_count_t len) ;
sf_count_t (*write_float) (struct sf_private_tag*, const float *ptr, sf_count_t len) ;
sf_count_t (*write_double) (struct sf_private_tag*, const double *ptr, sf_count_t len) ;
sf_count_t (*seek) (struct sf_private_tag*, int mode, sf_count_t samples_from_start) ;
int (*write_header) (struct sf_private_tag*, int calc_length) ;
int (*command) (struct sf_private_tag*, int command, void *data, int datasize) ;
/*
** Separate close functions for the codec and the container.
** The codec close function is always called first.
*/
int (*codec_close) (struct sf_private_tag*) ;
int (*container_close) (struct sf_private_tag*) ;
char *format_desc ;
/* Virtual I/O functions. */
int virtual_io ;
SF_VIRTUAL_IO vio ;
void *vio_user_data ;
} SF_PRIVATE ;
enum
{ SFE_NO_ERROR = SF_ERR_NO_ERROR,
SFE_BAD_OPEN_FORMAT = SF_ERR_UNRECOGNISED_FORMAT,
SFE_SYSTEM = SF_ERR_SYSTEM,
SFE_MALFORMED_FILE = SF_ERR_MALFORMED_FILE,
SFE_UNSUPPORTED_ENCODING = SF_ERR_UNSUPPORTED_ENCODING,
SFE_BAD_FILE,
SFE_BAD_FILE_READ,
SFE_OPEN_FAILED,
SFE_BAD_SNDFILE_PTR,
SFE_BAD_SF_INFO_PTR,
SFE_BAD_SF_INCOMPLETE,
SFE_BAD_FILE_PTR,
SFE_BAD_INT_PTR,
SFE_BAD_STAT_SIZE,
SFE_MALLOC_FAILED,
SFE_UNIMPLEMENTED,
SFE_BAD_READ_ALIGN,
SFE_BAD_WRITE_ALIGN,
SFE_UNKNOWN_FORMAT,
SFE_NOT_READMODE,
SFE_NOT_WRITEMODE,
SFE_BAD_MODE_RW,
SFE_BAD_SF_INFO,
SFE_BAD_OFFSET,
SFE_NO_EMBED_SUPPORT,
SFE_NO_EMBEDDED_RDWR,
SFE_NO_PIPE_WRITE,
SFE_INTERNAL,
SFE_BAD_CONTROL_CMD,
SFE_BAD_ENDIAN,
SFE_CHANNEL_COUNT,
SFE_BAD_RDWR_FORMAT,
SFE_BAD_VIRTUAL_IO,
SFE_INTERLEAVE_MODE,
SFE_INTERLEAVE_SEEK,
SFE_INTERLEAVE_READ,
SFE_BAD_SEEK,
SFE_NOT_SEEKABLE,
SFE_AMBIGUOUS_SEEK,
SFE_WRONG_SEEK,
SFE_SEEK_FAILED,
SFE_BAD_OPEN_MODE,
SFE_OPEN_PIPE_RDWR,
SFE_RDWR_POSITION,
SFE_RDWR_BAD_HEADER,
SFE_STR_NO_SUPPORT,
SFE_STR_NOT_WRITE,
SFE_STR_MAX_DATA,
SFE_STR_MAX_COUNT,
SFE_STR_BAD_TYPE,
SFE_STR_NO_ADD_END,
SFE_STR_BAD_STRING,
SFE_STR_WEIRD,
SFE_WAV_NO_RIFF,
SFE_WAV_NO_WAVE,
SFE_WAV_NO_FMT,
SFE_WAV_FMT_SHORT,
SFE_WAV_BAD_FACT,
SFE_WAV_BAD_PEAK,
SFE_WAV_PEAK_B4_FMT,
SFE_WAV_BAD_FORMAT,
SFE_WAV_BAD_BLOCKALIGN,
SFE_WAV_NO_DATA,
SFE_WAV_BAD_LIST,
SFE_WAV_ADPCM_NOT4BIT,
SFE_WAV_ADPCM_CHANNELS,
SFE_WAV_GSM610_FORMAT,
SFE_WAV_UNKNOWN_CHUNK,
SFE_WAV_WVPK_DATA,
SFE_AIFF_NO_FORM,
SFE_AIFF_AIFF_NO_FORM,
SFE_AIFF_COMM_NO_FORM,
SFE_AIFF_SSND_NO_COMM,
SFE_AIFF_UNKNOWN_CHUNK,
SFE_AIFF_COMM_CHUNK_SIZE,
SFE_AIFF_BAD_COMM_CHUNK,
SFE_AIFF_PEAK_B4_COMM,
SFE_AIFF_BAD_PEAK,
SFE_AIFF_NO_SSND,
SFE_AIFF_NO_DATA,
SFE_AIFF_RW_SSND_NOT_LAST,
SFE_AU_UNKNOWN_FORMAT,
SFE_AU_NO_DOTSND,
SFE_AU_EMBED_BAD_LEN,
SFE_RAW_READ_BAD_SPEC,
SFE_RAW_BAD_BITWIDTH,
SFE_RAW_BAD_FORMAT,
SFE_PAF_NO_MARKER,
SFE_PAF_VERSION,
SFE_PAF_UNKNOWN_FORMAT,
SFE_PAF_SHORT_HEADER,
SFE_SVX_NO_FORM,
SFE_SVX_NO_BODY,
SFE_SVX_NO_DATA,
SFE_SVX_BAD_COMP,
SFE_SVX_BAD_NAME_LENGTH,
SFE_NIST_BAD_HEADER,
SFE_NIST_CRLF_CONVERISON,
SFE_NIST_BAD_ENCODING,
SFE_VOC_NO_CREATIVE,
SFE_VOC_BAD_FORMAT,
SFE_VOC_BAD_VERSION,
SFE_VOC_BAD_MARKER,
SFE_VOC_BAD_SECTIONS,
SFE_VOC_MULTI_SAMPLERATE,
SFE_VOC_MULTI_SECTION,
SFE_VOC_MULTI_PARAM,
SFE_VOC_SECTION_COUNT,
SFE_VOC_NO_PIPE,
SFE_IRCAM_NO_MARKER,
SFE_IRCAM_BAD_CHANNELS,
SFE_IRCAM_UNKNOWN_FORMAT,
SFE_W64_64_BIT,
SFE_W64_NO_RIFF,
SFE_W64_NO_WAVE,
SFE_W64_NO_FMT,
SFE_W64_NO_DATA,
SFE_W64_FMT_SHORT,
SFE_W64_FMT_TOO_BIG,
SFE_W64_ADPCM_NOT4BIT,
SFE_W64_ADPCM_CHANNELS,
SFE_W64_GSM610_FORMAT,
SFE_MAT4_BAD_NAME,
SFE_MAT4_NO_SAMPLERATE,
SFE_MAT4_ZERO_CHANNELS,
SFE_MAT5_BAD_ENDIAN,
SFE_MAT5_NO_BLOCK,
SFE_MAT5_SAMPLE_RATE,
SFE_MAT5_ZERO_CHANNELS,
SFE_PVF_NO_PVF1,
SFE_PVF_BAD_HEADER,
SFE_PVF_BAD_BITWIDTH,
SFE_DWVW_BAD_BITWIDTH,
SFE_G72X_NOT_MONO,
SFE_XI_BAD_HEADER,
SFE_XI_EXCESS_SAMPLES,
SFE_XI_NO_PIPE,
SFE_HTK_NO_PIPE,
SFE_SDS_NOT_SDS,
SFE_SDS_BAD_BIT_WIDTH,
SFE_SD2_FD_DISALLOWED,
SFE_SD2_BAD_DATA_OFFSET,
SFE_SD2_BAD_MAP_OFFSET,
SFE_SD2_BAD_DATA_LENGTH,
SFE_SD2_BAD_MAP_LENGTH,
SFE_SD2_BAD_RSRC,
SFE_SD2_BAD_SAMPLE_SIZE,
SFE_FLAC_BAD_HEADER,
SFE_FLAC_NEW_DECODER,
SFE_FLAC_INIT_DECODER,
SFE_FLAC_LOST_SYNC,
SFE_FLAC_BAD_SAMPLE_RATE,
SFE_FLAC_UNKOWN_ERROR,
SFE_MAX_ERROR /* This must be last in list. */
} ;
int subformat_to_bytewidth (int format) ;
int s_bitwidth_to_subformat (int bits) ;
int u_bitwidth_to_subformat (int bits) ;
/* Functions for reading and writing floats and doubles on processors
** with non-IEEE floats/doubles.
*/
float float32_be_read (unsigned char *cptr) ;
float float32_le_read (unsigned char *cptr) ;
void float32_be_write (float in, unsigned char *out) ;
void float32_le_write (float in, unsigned char *out) ;
double double64_be_read (unsigned char *cptr) ;
double double64_le_read (unsigned char *cptr) ;
void double64_be_write (double in, unsigned char *out) ;
void double64_le_write (double in, unsigned char *out) ;
/* Functions for writing to the internal logging buffer. */
void psf_log_printf (SF_PRIVATE *psf, const char *format, ...) ;
void psf_log_SF_INFO (SF_PRIVATE *psf) ;
void psf_hexdump (void *ptr, int len) ;
/* Functions used when writing file headers. */
int psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) ;
void psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...) ;
/* Functions used when reading file headers. */
int psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) ;
/* Functions used in the write function for updating the peak chunk. */
void peak_update_short (SF_PRIVATE *psf, short *ptr, size_t items) ;
void peak_update_int (SF_PRIVATE *psf, int *ptr, size_t items) ;
void peak_update_double (SF_PRIVATE *psf, double *ptr, size_t items) ;
/* Functions defined in command.c. */
int psf_get_format_simple_count (void) ;
int psf_get_format_simple (SF_FORMAT_INFO *data) ;
int psf_get_format_info (SF_FORMAT_INFO *data) ;
int psf_get_format_major_count (void) ;
int psf_get_format_major (SF_FORMAT_INFO *data) ;
int psf_get_format_subtype_count (void) ;
int psf_get_format_subtype (SF_FORMAT_INFO *data) ;
void psf_generate_format_desc (SF_PRIVATE *psf) ;
double psf_calc_signal_max (SF_PRIVATE *psf, int normalize) ;
int psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize) ;
int psf_get_signal_max (SF_PRIVATE *psf, double *peak) ;
int psf_get_max_all_channels (SF_PRIVATE *psf, double *peaks) ;
/* Functions in strings.c. */
const char* psf_get_string (SF_PRIVATE *psf, int str_type) ;
int psf_set_string (SF_PRIVATE *psf, int str_type, const char *str) ;
int psf_store_string (SF_PRIVATE *psf, int str_type, const char *str) ;
/* Default seek function. Use for PCM and float encoded data. */
sf_count_t psf_default_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start) ;
/* Generate the currebt date as a string. */
void psf_get_date_str (char *str, int maxlen) ;
int macos_guess_file_type (SF_PRIVATE *psf, const char *filename) ;
/*------------------------------------------------------------------------------------
** File I/O functions which will allow access to large files (> 2 Gig) on
** some 32 bit OSes. Implementation in file_io.c.
*/
int psf_fopen (SF_PRIVATE *psf, const char *pathname, int flags) ;
int psf_set_stdio (SF_PRIVATE *psf, int mode) ;
int psf_file_valid (SF_PRIVATE *psf) ;
void psf_set_file (SF_PRIVATE *psf, int fd) ;
void psf_init_files (SF_PRIVATE *psf) ;
void psf_use_rsrc (SF_PRIVATE *psf, int on_off) ;
sf_count_t psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) ;
sf_count_t psf_fread (void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ;
sf_count_t psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ;
sf_count_t psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) ;
sf_count_t psf_ftell (SF_PRIVATE *psf) ;
sf_count_t psf_get_filelen (SF_PRIVATE *psf) ;
void psf_fsync (SF_PRIVATE *psf) ;
int psf_is_pipe (SF_PRIVATE *psf) ;
int psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) ;
int psf_fclose (SF_PRIVATE *psf) ;
/* Open and close the resource fork of a file. */
int psf_open_rsrc (SF_PRIVATE *psf, int mode) ;
int psf_close_rsrc (SF_PRIVATE *psf) ;
/*
void psf_fclearerr (SF_PRIVATE *psf) ;
int psf_ferror (SF_PRIVATE *psf) ;
*/
/*------------------------------------------------------------------------------------
** Functions for reading and writing different file formats.
*/
int aiff_open (SF_PRIVATE *psf) ;
int au_open (SF_PRIVATE *psf) ;
int avr_open (SF_PRIVATE *psf) ;
int htk_open (SF_PRIVATE *psf) ;
int ircam_open (SF_PRIVATE *psf) ;
int mat4_open (SF_PRIVATE *psf) ;
int mat5_open (SF_PRIVATE *psf) ;
int nist_open (SF_PRIVATE *psf) ;
int paf_open (SF_PRIVATE *psf) ;
int pvf_open (SF_PRIVATE *psf) ;
int raw_open (SF_PRIVATE *psf) ;
int sd2_open (SF_PRIVATE *psf) ;
int sds_open (SF_PRIVATE *psf) ;
int svx_open (SF_PRIVATE *psf) ;
int voc_open (SF_PRIVATE *psf) ;
int w64_open (SF_PRIVATE *psf) ;
int wav_open (SF_PRIVATE *psf) ;
int xi_open (SF_PRIVATE *psf) ;
int flac_open (SF_PRIVATE *psf) ;
int caf_open (SF_PRIVATE *psf) ;
/* In progress. Do not currently work. */
int mpeg_open (SF_PRIVATE *psf) ;
int ogg_open (SF_PRIVATE *psf) ;
int rx2_open (SF_PRIVATE *psf) ;
int txw_open (SF_PRIVATE *psf) ;
int wve_open (SF_PRIVATE *psf) ;
int dwd_open (SF_PRIVATE *psf) ;
int macbinary3_open (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------------
** Init functions for a number of common data encodings.
*/
int pcm_init (SF_PRIVATE *psf) ;
int ulaw_init (SF_PRIVATE *psf) ;
int alaw_init (SF_PRIVATE *psf) ;
int float32_init (SF_PRIVATE *psf) ;
int double64_init (SF_PRIVATE *psf) ;
int dwvw_init (SF_PRIVATE *psf, int bitwidth) ;
int gsm610_init (SF_PRIVATE *psf) ;
int vox_adpcm_init (SF_PRIVATE *psf) ;
int flac_init (SF_PRIVATE *psf) ;
int g72x_init (SF_PRIVATE * psf) ;
int dither_init (SF_PRIVATE *psf, int mode) ;
int wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
int wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
int aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
int interleave_init (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------------
** Other helper functions.
*/
void *psf_memset (void *s, int c, sf_count_t n) ;
SF_INSTRUMENT * psf_instrument_alloc (void) ;
SF_BROADCAST_INFO* broadcast_info_alloc (void) ;
int broadcast_info_copy (SF_BROADCAST_INFO* dst, SF_BROADCAST_INFO* src) ;
int broadcast_add_coding_history (SF_BROADCAST_INFO* bext, unsigned int channels, unsigned int samplerate) ;
/*------------------------------------------------------------------------------------
** Here's how we fix systems which don't snprintf / vsnprintf.
** Systems without these functions should use the
*/
#if USE_WINDOWS_API
#define LSF_SNPRINTF _snprintf
#elif (HAVE_SNPRINTF && ! FORCE_MISSING_SNPRINTF)
#define LSF_SNPRINTF snprintf
#else
int missing_snprintf (char *str, size_t n, char const *fmt, ...) ;
#define LSF_SNPRINTF missing_snprintf
#endif
#if USE_WINDOWS_API
#define LSF_VSNPRINTF _vsnprintf
#elif (HAVE_VSNPRINTF && ! FORCE_MISSING_SNPRINTF)
#define LSF_VSNPRINTF vsnprintf
#else
int missing_vsnprintf (char *str, size_t n, const char *fmt, ...) ;
#define LSF_VSNPRINTF missing_vsnprintf
#endif
/*------------------------------------------------------------------------------------
** Extra commands for sf_command(). Not for public use yet.
*/
enum
{ SFC_TEST_AIFF_ADD_INST_CHUNK = 0x2000,
SFC_TEST_WAV_ADD_INFO_CHUNK = 0x2010
} ;
/*
** Maybe, one day, make these functions or something like them, public.
**
** Buffer to buffer dithering. Pointer in and out are allowed to point
** to the same buffer for in-place dithering.
*/
#if 0
int sf_dither_short (const SF_DITHER_INFO *dither, const short *in, short *out, int count) ;
int sf_dither_int (const SF_DITHER_INFO *dither, const int *in, int *out, int count) ;
int sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out, int count) ;
int sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int count) ;
#endif
#endif /* SNDFILE_COMMON_H */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 7b45c0ee-5835-4a18-a4ef-994e4cd95b67
*/

View File

@@ -0,0 +1,247 @@
/* src/config.h.in. Generated from configure.ac by autoheader. */
/* Set to 1 if the compile is GNU GCC. */
#undef COMPILER_IS_GCC
/* Target processor clips on negative float to int conversion. */
#undef CPU_CLIPS_NEGATIVE
/* Target processor clips on positive float to int conversion. */
#undef CPU_CLIPS_POSITIVE
/* Target processor is big endian. */
#undef CPU_IS_BIG_ENDIAN
/* Target processor is little endian. */
#undef CPU_IS_LITTLE_ENDIAN
/* Set to 1 to enable experimental code. */
#undef ENABLE_EXPERIMENTAL_CODE
/* Major version of GCC or 3 otherwise. */
#undef GCC_MAJOR_VERSION
/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
#undef HAVE_ALSA_ASOUNDLIB_H
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
/* Define to 1 if you have the `calloc' function. */
#undef HAVE_CALLOC
/* Define to 1 if you have the `ceil' function. */
#undef HAVE_CEIL
/* Set to 1 if S_IRGRP is defined. */
#undef HAVE_DECL_S_IRGRP
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define to 1 if you have the `fdatasync' function. */
#undef HAVE_FDATASYNC
/* Define to 1 if you have libflac 1.1.1 */
#undef HAVE_FLAC_1_1_1
/* Define to 1 if you have the <FLAC/all.h> header file. */
#undef HAVE_FLAC_ALL_H
/* Set to 1 if the compile supports the struct hack. */
#undef HAVE_FLEXIBLE_ARRAY
/* Define to 1 if you have the `floor' function. */
#undef HAVE_FLOOR
/* Define to 1 if you have the `fmod' function. */
#undef HAVE_FMOD
/* Define to 1 if you have the `free' function. */
#undef HAVE_FREE
/* Define to 1 if you have the `fstat' function. */
#undef HAVE_FSTAT
/* Define to 1 if you have the `fsync' function. */
#undef HAVE_FSYNC
/* Define to 1 if you have the `ftruncate' function. */
#undef HAVE_FTRUNCATE
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE
/* Define to 1 if you have the `gmtime' function. */
#undef HAVE_GMTIME
/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define if you have C99's lrint function. */
#undef HAVE_LRINT
/* Define if you have C99's lrintf function. */
#undef HAVE_LRINTF
/* Define to 1 if you have the `lseek' function. */
#undef HAVE_LSEEK
/* Define to 1 if you have the `malloc' function. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mmap' function. */
#undef HAVE_MMAP
/* Define to 1 if you have the `open' function. */
#undef HAVE_OPEN
/* Define to 1 if you have the `pread' function. */
#undef HAVE_PREAD
/* Define to 1 if you have the `pwrite' function. */
#undef HAVE_PWRITE
/* Define to 1 if you have the `read' function. */
#undef HAVE_READ
/* Define to 1 if you have the `realloc' function. */
#undef HAVE_REALLOC
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Set to 1 if you have libsqlite3. */
#undef HAVE_SQLITE3
/* Define to 1 if the system has the type `ssize_t'. */
#undef HAVE_SSIZE_T
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to 1 if you have the `write' function. */
#undef HAVE_WRITE
/* Set to 1 if compiling for MacOSX */
#undef OS_IS_MACOSX
/* Set to 1 if compiling for Win32 */
#undef OS_IS_WIN32
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Set to maximum allowed value of sf_count_t type. */
#undef SF_COUNT_MAX
/* The size of a `double', as computed by sizeof. */
#undef SIZEOF_DOUBLE
/* The size of a `float', as computed by sizeof. */
#undef SIZEOF_FLOAT
/* The size of a `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of a `int64_t', as computed by sizeof. */
#undef SIZEOF_INT64_T
/* The size of a `loff_t', as computed by sizeof. */
#undef SIZEOF_LOFF_T
/* The size of a `long', as computed by sizeof. */
#undef SIZEOF_LONG
/* The size of a `long long', as computed by sizeof. */
#undef SIZEOF_LONG_LONG
/* The size of a `off64_t', as computed by sizeof. */
#undef SIZEOF_OFF64_T
/* The size of a `off_t', as computed by sizeof. */
#undef SIZEOF_OFF_T
/* Set to sizeof (long) if unknown. */
#undef SIZEOF_SF_COUNT_T
/* The size of a `short', as computed by sizeof. */
#undef SIZEOF_SHORT
/* The size of a `size_t', as computed by sizeof. */
#undef SIZEOF_SIZE_T
/* The size of a `ssize_t', as computed by sizeof. */
#undef SIZEOF_SSIZE_T
/* The size of a `void*', as computed by sizeof. */
#undef SIZEOF_VOIDP
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Set to long if unknown. */
#undef TYPEOF_SF_COUNT_T
/* Set to 1 to use the native windows API */
#undef USE_WINDOWS_API
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define to make fseeko etc. visible, on some hosts. */
#undef _LARGEFILE_SOURCE
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES

View File

@@ -0,0 +1,39 @@
; Auto-generated by create_symbols_file.py
LIBRARY cygsndfile-1.dll
EXPORTS
sf_command @1
sf_open @2
sf_close @3
sf_seek @4
sf_error @7
sf_perror @8
sf_error_str @9
sf_error_number @10
sf_format_check @11
sf_read_raw @16
sf_readf_short @17
sf_readf_int @18
sf_readf_float @19
sf_readf_double @20
sf_read_short @21
sf_read_int @22
sf_read_float @23
sf_read_double @24
sf_write_raw @32
sf_writef_short @33
sf_writef_int @34
sf_writef_float @35
sf_writef_double @36
sf_write_short @37
sf_write_int @38
sf_write_float @39
sf_write_double @40
sf_strerror @50
sf_get_string @60
sf_set_string @61
sf_open_fd @70
sf_open_virtual @80
sf_write_sync @90

View File

@@ -0,0 +1,535 @@
/*
** Copyright (C) 2003,2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdlib.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*============================================================================
** Rule number 1 is to only apply dither when going from a larger bitwidth
** to a smaller bitwidth. This can happen on both read and write.
**
** Need to apply dither on all conversions marked X below.
**
** Dither on write:
**
** Input
** | short int float double
** --------+-----------------------------------------------
** O 8 bit | X X X X
** u 16 bit | none X X X
** t 24 bit | none X X X
** p 32 bit | none none X X
** u float | none none none none
** t double | none none none none
**
** Dither on read:
**
** Input
** O | 8 bit 16 bit 24 bit 32 bit float double
** u --------+-------------------------------------------------
** t short | none none X X X X
** p int | none none none X X X
** u float | none none none none none none
** t double | none none none none none none
*/
#define SFE_DITHER_BAD_PTR 666
#define SFE_DITHER_BAD_TYPE 667
typedef struct
{ int read_short_dither_bits, read_int_dither_bits ;
int write_short_dither_bits, write_int_dither_bits ;
double read_float_dither_scale, read_double_dither_bits ;
double write_float_dither_scale, write_double_dither_bits ;
sf_count_t (*read_short) (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
sf_count_t (*read_int) (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
sf_count_t (*read_float) (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
sf_count_t (*read_double) (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
sf_count_t (*write_short) (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
sf_count_t (*write_int) (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
sf_count_t (*write_float) (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
sf_count_t (*write_double) (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
double buffer [SF_BUFFER_LEN / sizeof (double)] ;
} DITHER_DATA ;
static sf_count_t dither_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t dither_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t dither_write_short (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t dither_write_int (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t dither_write_float (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t dither_write_double (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
int
dither_init (SF_PRIVATE *psf, int mode)
{ DITHER_DATA *pdither ;
pdither = psf->dither ; /* This may be NULL. */
/* Turn off dither on read. */
if (mode == SFM_READ && psf->read_dither.type == SFD_NO_DITHER)
{ if (pdither == NULL)
return 0 ; /* Dither is already off, so just return. */
if (pdither->read_short)
psf->read_short = pdither->read_short ;
if (pdither->read_int)
psf->read_int = pdither->read_int ;
if (pdither->read_float)
psf->read_float = pdither->read_float ;
if (pdither->read_double)
psf->read_double = pdither->read_double ;
return 0 ;
} ;
/* Turn off dither on write. */
if (mode == SFM_WRITE && psf->write_dither.type == SFD_NO_DITHER)
{ if (pdither == NULL)
return 0 ; /* Dither is already off, so just return. */
if (pdither->write_short)
psf->write_short = pdither->write_short ;
if (pdither->write_int)
psf->write_int = pdither->write_int ;
if (pdither->write_float)
psf->write_float = pdither->write_float ;
if (pdither->write_double)
psf->write_double = pdither->write_double ;
return 0 ;
} ;
/* Turn on dither on read if asked. */
if (mode == SFM_READ && psf->read_dither.type != 0)
{ if (pdither == NULL)
pdither = psf->dither = calloc (1, sizeof (DITHER_DATA)) ;
if (pdither == NULL)
return SFE_MALLOC_FAILED ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_DOUBLE :
case SF_FORMAT_FLOAT :
pdither->read_int = psf->read_int ;
psf->read_int = dither_read_int ;
case SF_FORMAT_PCM_32 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
pdither->read_short = psf->read_short ;
psf->read_short = dither_read_short ;
default : break ;
} ;
} ;
/* Turn on dither on write if asked. */
if (mode == SFM_WRITE && psf->write_dither.type != 0)
{ if (pdither == NULL)
pdither = psf->dither = calloc (1, sizeof (DITHER_DATA)) ;
if (pdither == NULL)
return SFE_MALLOC_FAILED ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_DOUBLE :
case SF_FORMAT_FLOAT :
pdither->write_int = psf->write_int ;
psf->write_int = dither_write_int ;
case SF_FORMAT_PCM_32 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
default : break ;
} ;
pdither->write_short = psf->write_short ;
psf->write_short = dither_write_short ;
pdither->write_int = psf->write_int ;
psf->write_int = dither_write_int ;
pdither->write_float = psf->write_float ;
psf->write_float = dither_write_float ;
pdither->write_double = psf->write_double ;
psf->write_double = dither_write_double ;
} ;
return 0 ;
} /* dither_init */
/*==============================================================================
*/
static void dither_short (const short *in, short *out, int frames, int channels) ;
static void dither_int (const int *in, int *out, int frames, int channels) ;
static void dither_float (const float *in, float *out, int frames, int channels) ;
static void dither_double (const double *in, double *out, int frames, int channels) ;
static sf_count_t
dither_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ psf = psf ;
ptr = ptr ;
return len ;
} /* dither_read_short */
static sf_count_t
dither_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ psf = psf ;
ptr = ptr ;
return len ;
} /* dither_read_int */
/*------------------------------------------------------------------------------
*/
static sf_count_t
dither_write_short (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ DITHER_DATA *pdither ;
int bufferlen, writecount, thiswrite ;
sf_count_t total = 0 ;
if ((pdither = psf->dither) == NULL)
{ psf->error = SFE_DITHER_BAD_PTR ;
return 0 ;
} ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
case SF_FORMAT_DPCM_8 :
break ;
default :
return pdither->write_short (psf, ptr, len) ;
} ;
bufferlen = sizeof (pdither->buffer) / sizeof (short) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
writecount /= psf->sf.channels ;
writecount *= psf->sf.channels ;
dither_short (ptr, (short*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
thiswrite = pdither->write_short (psf, (short*) pdither->buffer, writecount) ;
total += thiswrite ;
len -= thiswrite ;
if (thiswrite < writecount)
break ;
} ;
return total ;
} /* dither_write_short */
static sf_count_t
dither_write_int (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ DITHER_DATA *pdither ;
int bufferlen, writecount, thiswrite ;
sf_count_t total = 0 ;
if ((pdither = psf->dither) == NULL)
{ psf->error = SFE_DITHER_BAD_PTR ;
return 0 ;
} ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_DPCM_8 :
case SF_FORMAT_DPCM_16 :
break ;
default :
return pdither->write_int (psf, ptr, len) ;
} ;
bufferlen = sizeof (pdither->buffer) / sizeof (int) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
writecount /= psf->sf.channels ;
writecount *= psf->sf.channels ;
dither_int (ptr, (int*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
thiswrite = pdither->write_int (psf, (int*) pdither->buffer, writecount) ;
total += thiswrite ;
len -= thiswrite ;
if (thiswrite < writecount)
break ;
} ;
return total ;
} /* dither_write_int */
static sf_count_t
dither_write_float (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ DITHER_DATA *pdither ;
int bufferlen, writecount, thiswrite ;
sf_count_t total = 0 ;
if ((pdither = psf->dither) == NULL)
{ psf->error = SFE_DITHER_BAD_PTR ;
return 0 ;
} ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_DPCM_8 :
case SF_FORMAT_DPCM_16 :
break ;
default :
return pdither->write_float (psf, ptr, len) ;
} ;
bufferlen = sizeof (pdither->buffer) / sizeof (float) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (float) len ;
writecount /= psf->sf.channels ;
writecount *= psf->sf.channels ;
dither_float (ptr, (float*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
thiswrite = pdither->write_float (psf, (float*) pdither->buffer, writecount) ;
total += thiswrite ;
len -= thiswrite ;
if (thiswrite < writecount)
break ;
} ;
return total ;
} /* dither_write_float */
static sf_count_t
dither_write_double (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ DITHER_DATA *pdither ;
int bufferlen, writecount, thiswrite ;
sf_count_t total = 0 ;
if ((pdither = psf->dither) == NULL)
{ psf->error = SFE_DITHER_BAD_PTR ;
return 0 ;
} ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_DPCM_8 :
case SF_FORMAT_DPCM_16 :
break ;
default :
return pdither->write_double (psf, ptr, len) ;
} ;
bufferlen = sizeof (pdither->buffer) / sizeof (double) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (double) len ;
writecount /= psf->sf.channels ;
writecount *= psf->sf.channels ;
dither_double (ptr, (double*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
thiswrite = pdither->write_double (psf, (double*) pdither->buffer, writecount) ;
total += thiswrite ;
len -= thiswrite ;
if (thiswrite < writecount)
break ;
} ;
return total ;
} /* dither_write_double */
/*==============================================================================
*/
static void
dither_short (const short *in, short *out, int frames, int channels)
{ int ch, k ;
for (ch = 0 ; ch < channels ; ch++)
for (k = ch ; k < channels * frames ; k += channels)
out [k] = in [k] ;
} /* dither_short */
static void
dither_int (const int *in, int *out, int frames, int channels)
{ int ch, k ;
for (ch = 0 ; ch < channels ; ch++)
for (k = ch ; k < channels * frames ; k += channels)
out [k] = in [k] ;
} /* dither_int */
static void
dither_float (const float *in, float *out, int frames, int channels)
{ int ch, k ;
for (ch = 0 ; ch < channels ; ch++)
for (k = ch ; k < channels * frames ; k += channels)
out [k] = in [k] ;
} /* dither_float */
static void
dither_double (const double *in, double *out, int frames, int channels)
{ int ch, k ;
for (ch = 0 ; ch < channels ; ch++)
for (k = ch ; k < channels * frames ; k += channels)
out [k] = in [k] ;
} /* dither_double */
/*==============================================================================
*/
#if 0
/*
** Not made public because this (maybe) requires storage of state information.
**
** Also maybe need separate state info for each channel!!!!
*/
int
DO_NOT_USE_sf_dither_short (const SF_DITHER_INFO *dither, const short *in, short *out, int frames, int channels)
{ int ch, k ;
if (! dither)
return SFE_DITHER_BAD_PTR ;
switch (dither->type & SFD_TYPEMASK)
{ case SFD_WHITE :
case SFD_TRIANGULAR_PDF :
for (ch = 0 ; ch < channels ; ch++)
for (k = ch ; k < channels * frames ; k += channels)
out [k] = in [k] ;
break ;
default :
return SFE_DITHER_BAD_TYPE ;
} ;
return 0 ;
} /* DO_NOT_USE_sf_dither_short */
int
DO_NOT_USE_sf_dither_int (const SF_DITHER_INFO *dither, const int *in, int *out, int frames, int channels)
{ int ch, k ;
if (! dither)
return SFE_DITHER_BAD_PTR ;
switch (dither->type & SFD_TYPEMASK)
{ case SFD_WHITE :
case SFD_TRIANGULAR_PDF :
for (ch = 0 ; ch < channels ; ch++)
for (k = ch ; k < channels * frames ; k += channels)
out [k] = in [k] ;
break ;
default :
return SFE_DITHER_BAD_TYPE ;
} ;
return 0 ;
} /* DO_NOT_USE_sf_dither_int */
int
DO_NOT_USE_sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out, int frames, int channels)
{ int ch, k ;
if (! dither)
return SFE_DITHER_BAD_PTR ;
switch (dither->type & SFD_TYPEMASK)
{ case SFD_WHITE :
case SFD_TRIANGULAR_PDF :
for (ch = 0 ; ch < channels ; ch++)
for (k = ch ; k < channels * frames ; k += channels)
out [k] = in [k] ;
break ;
default :
return SFE_DITHER_BAD_TYPE ;
} ;
return 0 ;
} /* DO_NOT_USE_sf_dither_float */
int
DO_NOT_USE_sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int frames, int channels)
{ int ch, k ;
if (! dither)
return SFE_DITHER_BAD_PTR ;
switch (dither->type & SFD_TYPEMASK)
{ case SFD_WHITE :
case SFD_TRIANGULAR_PDF :
for (ch = 0 ; ch < channels ; ch++)
for (k = ch ; k < channels * frames ; k += channels)
out [k] = in [k] ;
break ;
default :
return SFE_DITHER_BAD_TYPE ;
} ;
return 0 ;
} /* DO_NOT_USE_sf_dither_double */
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 673fad58-5314-421c-9144-9d54bfdf104c
*/

File diff suppressed because it is too large Load Diff

210
libs/libsndfile/src/dwd.c Normal file
View File

@@ -0,0 +1,210 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#if (ENABLE_EXPERIMENTAL_CODE == 0)
int
dwd_open (SF_PRIVATE *psf)
{ if (psf)
return SFE_UNIMPLEMENTED ;
return (psf && 0) ;
} /* dwd_open */
#else
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define SFE_DWD_NO_DWD 1666
#define SFE_DWD_BAND_BIT_WIDTH 1667
#define SFE_DWD_COMPRESSION 1668
#define DWD_IDENTIFIER "DiamondWare Digitized\n\0\x1a"
#define DWD_IDENTIFIER_LEN 24
#define DWD_HEADER_LEN 57
/*------------------------------------------------------------------------------
** Typedefs.
*/
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int dwd_read_header (SF_PRIVATE *psf) ;
static int dwd_close (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
dwd_open (SF_PRIVATE *psf)
{ int subformat, error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = dwd_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_DWD)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{
/*-psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)
psf->endian = SF_ENDIAN_LITTLE ;
else if (psf->endian != SF_ENDIAN_LITTLE)
psf->endian = SF_ENDIAN_BIG ;
if (! (encoding = dwd_write_header (psf, SF_FALSE)))
return psf->error ;
psf->write_header = dwd_write_header ;
-*/
} ;
psf->container_close = dwd_close ;
/*-psf->blockwidth = psf->bytewidth * psf->sf.channels ;-*/
return error ;
} /* dwd_open */
/*------------------------------------------------------------------------------
*/
static int
dwd_close (SF_PRIVATE *psf)
{
psf = psf ;
return 0 ;
} /* dwd_close */
/* This struct contains all the fields of interest om the DWD header, but does not
** do so in the same order and layout as the actual file, header.
** No assumptions are made about the packing of this struct.
*/
typedef struct
{ unsigned char major, minor, compression, channels, bitwidth ;
unsigned short srate, maxval ;
unsigned int id, datalen, frames, offset ;
} DWD_HEADER ;
static int
dwd_read_header (SF_PRIVATE *psf)
{ DWD_HEADER dwdh ;
memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
/* Set position to start of file to begin reading header. */
psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, DWD_IDENTIFIER_LEN) ;
if (memcmp (psf->u.cbuf, DWD_IDENTIFIER, DWD_IDENTIFIER_LEN) != 0)
return SFE_DWD_NO_DWD ;
psf_log_printf (psf, "Read only : DiamondWare Digitized (.dwd)\n", psf->u.cbuf) ;
psf_binheader_readf (psf, "11", &dwdh.major, &dwdh.minor) ;
psf_binheader_readf (psf, "e4j1", &dwdh.id, 1, &dwdh.compression) ;
psf_binheader_readf (psf, "e211", &dwdh.srate, &dwdh.channels, &dwdh.bitwidth) ;
psf_binheader_readf (psf, "e24", &dwdh.maxval, &dwdh.datalen) ;
psf_binheader_readf (psf, "e44", &dwdh.frames, &dwdh.offset) ;
psf_log_printf (psf, " Version Major : %d\n Version Minor : %d\n Unique ID : %08X\n",
dwdh.major, dwdh.minor, dwdh.id) ;
psf_log_printf (psf, " Compression : %d => ", dwdh.compression) ;
if (dwdh.compression != 0)
{ psf_log_printf (psf, "Unsupported compression\n") ;
return SFE_DWD_COMPRESSION ;
}
else
psf_log_printf (psf, "None\n") ;
psf_log_printf (psf, " Sample Rate : %d\n Channels : %d\n"
" Bit Width : %d\n",
dwdh.srate, dwdh.channels, dwdh.bitwidth) ;
switch (dwdh.bitwidth)
{ case 8 :
psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_S8 ;
psf->bytewidth = 1 ;
break ;
case 16 :
psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
break ;
default :
psf_log_printf (psf, "*** Bad bit width %d\n", dwdh.bitwidth) ;
return SFE_DWD_BAND_BIT_WIDTH ;
} ;
if (psf->filelength != dwdh.offset + dwdh.datalen)
{ psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ;
dwdh.datalen = (unsigned int) (psf->filelength - dwdh.offset) ;
}
else
psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ;
psf_log_printf (psf, " Max Value : %d\n", dwdh.maxval) ;
psf_log_printf (psf, " Frames : %d\n", dwdh.frames) ;
psf_log_printf (psf, " Data Offset : %d\n", dwdh.offset) ;
psf->datalength = dwdh.datalen ;
psf->dataoffset = dwdh.offset ;
psf->endian = SF_ENDIAN_LITTLE ;
psf->sf.samplerate = dwdh.srate ;
psf->sf.channels = dwdh.channels ;
psf->sf.sections = 1 ;
return pcm_init (psf) ;
} /* dwd_read_header */
/*------------------------------------------------------------------------------
*/
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a5e1d2a6-a840-4039-a0e7-e1a43eb05a4f
*/

671
libs/libsndfile/src/dwvw.c Normal file
View File

@@ -0,0 +1,671 @@
/*
** Copyright (C) 2002-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*===========================================================================
** Delta Word Variable Width
**
** This decoder and encoder were implemented using information found in this
** document : http://home.swbell.net/rubywand/R011SNDFMTS.TXT
**
** According to the document, the algorithm "was invented 1991 by Magnus
** Lidstrom and is copyright 1993 by NuEdge Development".
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
typedef struct
{ int dwm_maxsize, bit_width, max_delta, span ;
int samplecount ;
int bit_count, bits, last_delta_width, last_sample ;
struct
{ int index, end ;
unsigned char buffer [256] ;
} b ;
} DWVW_PRIVATE ;
/*============================================================================================
*/
static sf_count_t dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t dwvw_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static sf_count_t dwvw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int dwvw_close (SF_PRIVATE *psf) ;
static int dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) ;
static int dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count) ;
static int dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, const int *ptr, int len) ;
static void dwvw_encode_store_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int data, int new_bits) ;
static void dwvw_read_reset (DWVW_PRIVATE *pdwvw) ;
/*============================================================================================
** DWVW initialisation function.
*/
int
dwvw_init (SF_PRIVATE *psf, int bitwidth)
{ DWVW_PRIVATE *pdwvw ;
if (psf->fdata != NULL)
{ psf_log_printf (psf, "*** psf->fdata is not NULL.\n") ;
return SFE_INTERNAL ;
} ;
if (bitwidth > 24)
return SFE_DWVW_BAD_BITWIDTH ;
if (psf->mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
if ((pdwvw = calloc (1, sizeof (DWVW_PRIVATE))) == NULL)
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pdwvw ;
pdwvw->bit_width = bitwidth ;
pdwvw->dwm_maxsize = bitwidth / 2 ;
pdwvw->max_delta = 1 << (bitwidth - 1) ;
pdwvw->span = 1 << bitwidth ;
dwvw_read_reset (pdwvw) ;
if (psf->mode == SFM_READ)
{ psf->read_short = dwvw_read_s ;
psf->read_int = dwvw_read_i ;
psf->read_float = dwvw_read_f ;
psf->read_double = dwvw_read_d ;
} ;
if (psf->mode == SFM_WRITE)
{ psf->write_short = dwvw_write_s ;
psf->write_int = dwvw_write_i ;
psf->write_float = dwvw_write_f ;
psf->write_double = dwvw_write_d ;
} ;
psf->codec_close = dwvw_close ;
psf->seek = dwvw_seek ;
/* FIXME : This is bogus. */
psf->sf.frames = SF_COUNT_MAX ;
psf->datalength = psf->sf.frames ;
/* EMXIF : This is bogus. */
return 0 ;
} /* dwvw_init */
/*--------------------------------------------------------------------------------------------
*/
static int
dwvw_close (SF_PRIVATE *psf)
{ DWVW_PRIVATE *pdwvw ;
if (psf->fdata == NULL)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
if (psf->mode == SFM_WRITE)
{ static int last_values [12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
/* Write 8 zero samples to fully flush output. */
dwvw_encode_data (psf, pdwvw, last_values, 12) ;
/* Write the last buffer worth of data to disk. */
psf_fwrite (pdwvw->b.buffer, 1, pdwvw->b.index, psf) ;
if (psf->write_header)
psf->write_header (psf, SF_TRUE) ;
} ;
return 0 ;
} /* dwvw_close */
static sf_count_t
dwvw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{ DWVW_PRIVATE *pdwvw ;
mode = mode ;
if (! psf->fdata)
{ psf->error = SFE_INTERNAL ;
return PSF_SEEK_ERROR ;
} ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
if (offset == 0)
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
dwvw_read_reset (pdwvw) ;
return 0 ;
} ;
psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} /* dwvw_seek */
/*==============================================================================
*/
static sf_count_t
dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int *iptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = iptr [k] >> 16 ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* dwvw_read_s */
static sf_count_t
dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int readcount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
while (len > 0)
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = dwvw_decode_data (psf, pdwvw, ptr, readcount) ;
total += count ;
len -= count ;
if (count != readcount)
break ;
} ;
return total ;
} /* dwvw_read_i */
static sf_count_t
dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int *iptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (float) (iptr [k]) ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* dwvw_read_f */
static sf_count_t
dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int *iptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (double) (iptr [k]) ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* dwvw_read_d */
static int
dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len)
{ int count ;
int delta_width_modifier, delta_width, delta_negative, delta, sample ;
/* Restore state from last decode call. */
delta_width = pdwvw->last_delta_width ;
sample = pdwvw->last_sample ;
for (count = 0 ; count < len ; count++)
{ /* If bit_count parameter is zero get the delta_width_modifier. */
delta_width_modifier = dwvw_decode_load_bits (psf, pdwvw, -1) ;
/* Check for end of input bit stream. Break loop if end. */
if (delta_width_modifier < 0)
break ;
if (delta_width_modifier && dwvw_decode_load_bits (psf, pdwvw, 1))
delta_width_modifier = - delta_width_modifier ;
/* Calculate the current word width. */
delta_width = (delta_width + delta_width_modifier + pdwvw->bit_width) % pdwvw->bit_width ;
/* Load the delta. */
delta = 0 ;
if (delta_width)
{ delta = dwvw_decode_load_bits (psf, pdwvw, delta_width - 1) | (1 << (delta_width - 1)) ;
delta_negative = dwvw_decode_load_bits (psf, pdwvw, 1) ;
if (delta == pdwvw->max_delta - 1)
delta += dwvw_decode_load_bits (psf, pdwvw, 1) ;
if (delta_negative)
delta = -delta ;
} ;
/* Calculate the sample */
sample += delta ;
if (sample >= pdwvw->max_delta)
sample -= pdwvw->span ;
else if (sample < - pdwvw->max_delta)
sample += pdwvw->span ;
/* Store the sample justifying to the most significant bit. */
ptr [count] = sample << (32 - pdwvw->bit_width) ;
if (pdwvw->b.end == 0 && pdwvw->bit_count == 0)
break ;
} ;
pdwvw->last_delta_width = delta_width ;
pdwvw->last_sample = sample ;
pdwvw->samplecount += count ;
return count ;
} /* dwvw_decode_data */
static int
dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count)
{ int output = 0, get_dwm = SF_FALSE ;
/*
** Depending on the value of parameter bit_count, either get the
** required number of bits (ie bit_count > 0) or the
** delta_width_modifier (otherwise).
*/
if (bit_count < 0)
{ get_dwm = SF_TRUE ;
/* modify bit_count to ensure we have enought bits for finding dwm. */
bit_count = pdwvw->dwm_maxsize ;
} ;
/* Load bits in bit reseviour. */
while (pdwvw->bit_count < bit_count)
{ if (pdwvw->b.index >= pdwvw->b.end)
{ pdwvw->b.end = psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ;
pdwvw->b.index = 0 ;
} ;
/* Check for end of input stream. */
if (bit_count < 8 && pdwvw->b.end == 0)
return -1 ;
pdwvw->bits = (pdwvw->bits << 8) ;
if (pdwvw->b.index < pdwvw->b.end)
{ pdwvw->bits |= pdwvw->b.buffer [pdwvw->b.index] ;
pdwvw->b.index ++ ;
} ;
pdwvw->bit_count += 8 ;
} ;
/* If asked to get bits do so. */
if (! get_dwm)
{ output = (pdwvw->bits >> (pdwvw->bit_count - bit_count)) & ((1 << bit_count) - 1) ;
pdwvw->bit_count -= bit_count ;
return output ;
} ;
/* Otherwise must have been asked to get delta_width_modifier. */
while (output < (pdwvw->dwm_maxsize))
{ pdwvw->bit_count -= 1 ;
if (pdwvw->bits & (1 << pdwvw->bit_count))
break ;
output += 1 ;
} ;
return output ;
} /* dwvw_decode_load_bits */
static void
dwvw_read_reset (DWVW_PRIVATE *pdwvw)
{ pdwvw->samplecount = 0 ;
pdwvw->b.index = 0 ;
pdwvw->b.end = 0 ;
pdwvw->bit_count = 0 ;
pdwvw->bits = 0 ;
pdwvw->last_delta_width = 0 ;
pdwvw->last_sample = 0 ;
} /* dwvw_read_reset */
static void
dwvw_encode_store_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int data, int new_bits)
{ int byte ;
/* Shift the bits into the resevoir. */
pdwvw->bits = (pdwvw->bits << new_bits) | (data & ((1 << new_bits) - 1)) ;
pdwvw->bit_count += new_bits ;
/* Transfer bit to buffer. */
while (pdwvw->bit_count >= 8)
{ byte = pdwvw->bits >> (pdwvw->bit_count - 8) ;
pdwvw->bit_count -= 8 ;
pdwvw->b.buffer [pdwvw->b.index] = byte & 0xFF ;
pdwvw->b.index ++ ;
} ;
if (pdwvw->b.index > SIGNED_SIZEOF (pdwvw->b.buffer) - 4)
{ psf_fwrite (pdwvw->b.buffer, 1, pdwvw->b.index, psf) ;
pdwvw->b.index = 0 ;
} ;
return ;
} /* dwvw_encode_store_bits */
#if 0
/* Debigging routine. */
static void
dump_bits (DWVW_PRIVATE *pdwvw)
{ int k, mask ;
for (k = 0 ; k < 10 && k < pdwvw->b.index ; k++)
{ mask = 0x80 ;
while (mask)
{ putchar (mask & pdwvw->b.buffer [k] ? '1' : '0') ;
mask >>= 1 ;
} ;
putchar (' ') ;
}
for (k = pdwvw->bit_count - 1 ; k >= 0 ; k --)
putchar (pdwvw->bits & (1 << k) ? '1' : '0') ;
putchar ('\n') ;
} /* dump_bits */
#endif
#define HIGHEST_BIT(x,count) \
{ int y = x ; \
(count) = 0 ; \
while (y) \
{ (count) ++ ; \
y >>= 1 ; \
} ; \
} ;
static int
dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, const int *ptr, int len)
{ int count ;
int delta_width_modifier, delta, delta_negative, delta_width, extra_bit ;
for (count = 0 ; count < len ; count++)
{ delta = (ptr [count] >> (32 - pdwvw->bit_width)) - pdwvw->last_sample ;
/* Calculate extra_bit if needed. */
extra_bit = -1 ;
delta_negative = 0 ;
if (delta < -pdwvw->max_delta)
delta = pdwvw->max_delta + (delta % pdwvw->max_delta) ;
else if (delta == -pdwvw->max_delta)
{ extra_bit = 1 ;
delta_negative = 1 ;
delta = pdwvw->max_delta - 1 ;
}
else if (delta > pdwvw->max_delta)
{ delta_negative = 1 ;
delta = pdwvw->span - delta ;
delta = abs (delta) ;
}
else if (delta == pdwvw->max_delta)
{ extra_bit = 1 ;
delta = pdwvw->max_delta - 1 ;
}
else if (delta < 0)
{ delta_negative = 1 ;
delta = abs (delta) ;
} ;
if (delta == pdwvw->max_delta - 1 && extra_bit == -1)
extra_bit = 0 ;
/* Find width in bits of delta */
HIGHEST_BIT (delta, delta_width) ;
/* Calculate the delta_width_modifier */
delta_width_modifier = (delta_width - pdwvw->last_delta_width) % pdwvw->bit_width ;
if (delta_width_modifier > pdwvw->dwm_maxsize)
delta_width_modifier -= pdwvw->bit_width ;
if (delta_width_modifier < -pdwvw->dwm_maxsize)
delta_width_modifier += pdwvw->bit_width ;
/* Write delta_width_modifier zeros, followed by terminating '1'. */
dwvw_encode_store_bits (psf, pdwvw, 0, abs (delta_width_modifier)) ;
if (abs (delta_width_modifier) != pdwvw->dwm_maxsize)
dwvw_encode_store_bits (psf, pdwvw, 1, 1) ;
/* Write delta_width_modifier sign. */
if (delta_width_modifier < 0)
dwvw_encode_store_bits (psf, pdwvw, 1, 1) ;
if (delta_width_modifier > 0)
dwvw_encode_store_bits (psf, pdwvw, 0, 1) ;
/* Write delta and delta sign bit. */
if (delta_width)
{ dwvw_encode_store_bits (psf, pdwvw, delta, abs (delta_width) - 1) ;
dwvw_encode_store_bits (psf, pdwvw, (delta_negative ? 1 : 0), 1) ;
} ;
/* Write extra bit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
if (extra_bit >= 0)
dwvw_encode_store_bits (psf, pdwvw, extra_bit, 1) ;
pdwvw->last_sample = ptr [count] >> (32 - pdwvw->bit_width) ;
pdwvw->last_delta_width = delta_width ;
} ;
pdwvw->samplecount += count ;
return count ;
} /* dwvw_encode_data */
static sf_count_t
dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int *iptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = ptr [total + k] << 16 ;
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* dwvw_write_s */
static sf_count_t
dwvw_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
while (len > 0)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = dwvw_encode_data (psf, pdwvw, ptr, writecount) ;
total += count ;
len -= count ;
if (count != writecount)
break ;
} ;
return total ;
} /* dwvw_write_i */
static sf_count_t
dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int *iptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = lrintf (normfact * ptr [total + k]) ;
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* dwvw_write_f */
static sf_count_t
dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int *iptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = lrint (normfact * ptr [total + k]) ;
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* dwvw_write_d */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 1ca09552-b01f-4d7f-9bcf-612f834fe41d
*/

File diff suppressed because it is too large Load Diff

1156
libs/libsndfile/src/flac.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,961 @@
/*
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#include "float_cast.h"
#if CPU_IS_LITTLE_ENDIAN
#define FLOAT32_READ float32_le_read
#define FLOAT32_WRITE float32_le_write
#elif CPU_IS_BIG_ENDIAN
#define FLOAT32_READ float32_be_read
#define FLOAT32_WRITE float32_be_write
#endif
/*--------------------------------------------------------------------------------------------
** Processor floating point capabilities. float32_get_capability () returns one of the
** latter four values.
*/
enum
{ FLOAT_UNKNOWN = 0x00,
FLOAT_CAN_RW_LE = 0x12,
FLOAT_CAN_RW_BE = 0x23,
FLOAT_BROKEN_LE = 0x34,
FLOAT_BROKEN_BE = 0x45
} ;
/*--------------------------------------------------------------------------------------------
** Prototypes for private functions.
*/
static sf_count_t host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static void float32_peak_update (SF_PRIVATE *psf, const float *buffer, int count, sf_count_t indx) ;
static sf_count_t replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static void bf2f_array (float *buffer, int count) ;
static void f2bf_array (float *buffer, int count) ;
static int float32_get_capability (SF_PRIVATE *psf) ;
/*--------------------------------------------------------------------------------------------
** Exported functions.
*/
int
float32_init (SF_PRIVATE *psf)
{ static int float_caps ;
float_caps = float32_get_capability (psf) ;
psf->blockwidth = sizeof (float) * psf->sf.channels ;
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
{ switch (psf->endian + float_caps)
{ case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) :
psf->float_endswap = SF_FALSE ;
psf->read_short = host_read_f2s ;
psf->read_int = host_read_f2i ;
psf->read_float = host_read_f ;
psf->read_double = host_read_f2d ;
break ;
case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) :
psf->float_endswap = SF_FALSE ;
psf->read_short = host_read_f2s ;
psf->read_int = host_read_f2i ;
psf->read_float = host_read_f ;
psf->read_double = host_read_f2d ;
break ;
case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) :
psf->float_endswap = SF_TRUE ;
psf->read_short = host_read_f2s ;
psf->read_int = host_read_f2i ;
psf->read_float = host_read_f ;
psf->read_double = host_read_f2d ;
break ;
case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) :
psf->float_endswap = SF_TRUE ;
psf->read_short = host_read_f2s ;
psf->read_int = host_read_f2i ;
psf->read_float = host_read_f ;
psf->read_double = host_read_f2d ;
break ;
/* When the CPU is not IEEE compatible. */
case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) :
psf->float_endswap = SF_TRUE ;
psf->read_short = replace_read_f2s ;
psf->read_int = replace_read_f2i ;
psf->read_float = replace_read_f ;
psf->read_double = replace_read_f2d ;
break ;
case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) :
psf->float_endswap = SF_FALSE ;
psf->read_short = replace_read_f2s ;
psf->read_int = replace_read_f2i ;
psf->read_float = replace_read_f ;
psf->read_double = replace_read_f2d ;
break ;
case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) :
psf->float_endswap = SF_FALSE ;
psf->read_short = replace_read_f2s ;
psf->read_int = replace_read_f2i ;
psf->read_float = replace_read_f ;
psf->read_double = replace_read_f2d ;
break ;
case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) :
psf->float_endswap = SF_TRUE ;
psf->read_short = replace_read_f2s ;
psf->read_int = replace_read_f2i ;
psf->read_float = replace_read_f ;
psf->read_double = replace_read_f2d ;
break ;
default : break ;
} ;
} ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ switch (psf->endian + float_caps)
{ case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) :
psf->float_endswap = SF_FALSE ;
psf->write_short = host_write_s2f ;
psf->write_int = host_write_i2f ;
psf->write_float = host_write_f ;
psf->write_double = host_write_d2f ;
break ;
case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) :
psf->float_endswap = SF_FALSE ;
psf->write_short = host_write_s2f ;
psf->write_int = host_write_i2f ;
psf->write_float = host_write_f ;
psf->write_double = host_write_d2f ;
break ;
case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) :
psf->float_endswap = SF_TRUE ;
psf->write_short = host_write_s2f ;
psf->write_int = host_write_i2f ;
psf->write_float = host_write_f ;
psf->write_double = host_write_d2f ;
break ;
case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) :
psf->float_endswap = SF_TRUE ;
psf->write_short = host_write_s2f ;
psf->write_int = host_write_i2f ;
psf->write_float = host_write_f ;
psf->write_double = host_write_d2f ;
break ;
/* When the CPU is not IEEE compatible. */
case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) :
psf->float_endswap = SF_TRUE ;
psf->write_short = replace_write_s2f ;
psf->write_int = replace_write_i2f ;
psf->write_float = replace_write_f ;
psf->write_double = replace_write_d2f ;
break ;
case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) :
psf->float_endswap = SF_FALSE ;
psf->write_short = replace_write_s2f ;
psf->write_int = replace_write_i2f ;
psf->write_float = replace_write_f ;
psf->write_double = replace_write_d2f ;
break ;
case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) :
psf->float_endswap = SF_FALSE ;
psf->write_short = replace_write_s2f ;
psf->write_int = replace_write_i2f ;
psf->write_float = replace_write_f ;
psf->write_double = replace_write_d2f ;
break ;
case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) :
psf->float_endswap = SF_TRUE ;
psf->write_short = replace_write_s2f ;
psf->write_int = replace_write_i2f ;
psf->write_float = replace_write_f ;
psf->write_double = replace_write_d2f ;
break ;
default : break ;
} ;
} ;
if (psf->filelength > psf->dataoffset)
{ psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset :
psf->filelength - psf->dataoffset ;
}
else
psf->datalength = 0 ;
psf->sf.frames = psf->datalength / psf->blockwidth ;
return 0 ;
} /* float32_init */
float
float32_be_read (unsigned char *cptr)
{ int exponent, mantissa, negative ;
float fvalue ;
negative = cptr [0] & 0x80 ;
exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ;
mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ;
if (! (exponent || mantissa))
return 0.0 ;
mantissa |= 0x800000 ;
exponent = exponent ? exponent - 127 : 0 ;
fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ;
if (negative)
fvalue *= -1 ;
if (exponent > 0)
fvalue *= (1 << exponent) ;
else if (exponent < 0)
fvalue /= (1 << abs (exponent)) ;
return fvalue ;
} /* float32_be_read */
float
float32_le_read (unsigned char *cptr)
{ int exponent, mantissa, negative ;
float fvalue ;
negative = cptr [3] & 0x80 ;
exponent = ((cptr [3] & 0x7F) << 1) | ((cptr [2] & 0x80) ? 1 : 0) ;
mantissa = ((cptr [2] & 0x7F) << 16) | (cptr [1] << 8) | (cptr [0]) ;
if (! (exponent || mantissa))
return 0.0 ;
mantissa |= 0x800000 ;
exponent = exponent ? exponent - 127 : 0 ;
fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ;
if (negative)
fvalue *= -1 ;
if (exponent > 0)
fvalue *= (1 << exponent) ;
else if (exponent < 0)
fvalue /= (1 << abs (exponent)) ;
return fvalue ;
} /* float32_le_read */
void
float32_le_write (float in, unsigned char *out)
{ int exponent, mantissa, negative = 0 ;
memset (out, 0, sizeof (int)) ;
if (fabs (in) < 1e-30)
return ;
if (in < 0.0)
{ in *= -1.0 ;
negative = 1 ;
} ;
in = frexp (in, &exponent) ;
exponent += 126 ;
in *= (float) 0x1000000 ;
mantissa = (((int) in) & 0x7FFFFF) ;
if (negative)
out [3] |= 0x80 ;
if (exponent & 0x01)
out [2] |= 0x80 ;
out [0] = mantissa & 0xFF ;
out [1] = (mantissa >> 8) & 0xFF ;
out [2] |= (mantissa >> 16) & 0x7F ;
out [3] |= (exponent >> 1) & 0x7F ;
return ;
} /* float32_le_write */
void
float32_be_write (float in, unsigned char *out)
{ int exponent, mantissa, negative = 0 ;
memset (out, 0, sizeof (int)) ;
if (fabs (in) < 1e-30)
return ;
if (in < 0.0)
{ in *= -1.0 ;
negative = 1 ;
} ;
in = frexp (in, &exponent) ;
exponent += 126 ;
in *= (float) 0x1000000 ;
mantissa = (((int) in) & 0x7FFFFF) ;
if (negative)
out [0] |= 0x80 ;
if (exponent & 0x01)
out [1] |= 0x80 ;
out [3] = mantissa & 0xFF ;
out [2] = (mantissa >> 8) & 0xFF ;
out [1] |= (mantissa >> 16) & 0x7F ;
out [0] |= (exponent >> 1) & 0x7F ;
return ;
} /* float32_be_write */
/*==============================================================================================
** Private functions.
*/
static void
float32_peak_update (SF_PRIVATE *psf, const float *buffer, int count, sf_count_t indx)
{ int chan ;
int k, position ;
float fmaxval ;
for (chan = 0 ; chan < psf->sf.channels ; chan++)
{ fmaxval = fabs (buffer [chan]) ;
position = 0 ;
for (k = chan ; k < count ; k += psf->sf.channels)
if (fmaxval < fabs (buffer [k]))
{ fmaxval = fabs (buffer [k]) ;
position = k ;
} ;
if (fmaxval > psf->peak_info->peaks [chan].value)
{ psf->peak_info->peaks [chan].value = fmaxval ;
psf->peak_info->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ;
} ;
} ;
return ;
} /* float32_peak_update */
static int
float32_get_capability (SF_PRIVATE *psf)
{ union
{ float f ;
int i ;
unsigned char c [4] ;
} data ;
data.f = (float) 1.23456789 ; /* Some abitrary value. */
if (! psf->ieee_replace)
{ /* If this test is true ints and floats are compatible and little endian. */
if (data.c [0] == 0x52 && data.c [1] == 0x06 && data.c [2] == 0x9e && data.c [3] == 0x3f)
return FLOAT_CAN_RW_LE ;
/* If this test is true ints and floats are compatible and big endian. */
if (data.c [3] == 0x52 && data.c [2] == 0x06 && data.c [1] == 0x9e && data.c [0] == 0x3f)
return FLOAT_CAN_RW_BE ;
} ;
/* Floats are broken. Don't expect reading or writing to be fast. */
psf_log_printf (psf, "Using IEEE replacement code for float.\n") ;
return (CPU_IS_LITTLE_ENDIAN) ? FLOAT_BROKEN_LE : FLOAT_BROKEN_BE ;
} /* float32_get_capability */
/*=======================================================================================
*/
static inline void
f2s_array (const float *src, int count, short *dest, float scale)
{ while (--count >= 0)
{ dest [count] = lrintf (scale * src [count]) ;
} ;
} /* f2s_array */
static inline void
f2i_array (const float *src, int count, int *dest, float scale)
{ while (--count >= 0)
{ dest [count] = lrintf (scale * src [count]) ;
} ;
} /* f2i_array */
static inline void
f2d_array (const float *src, int count, double *dest)
{ while (--count >= 0)
{ dest [count] = src [count] ;
} ;
} /* f2d_array */
static inline void
s2f_array (const short *src, float *dest, int count)
{ while (--count >= 0)
{ dest [count] = src [count] ;
} ;
} /* s2f_array */
static inline void
i2f_array (const int *src, float *dest, int count)
{ while (--count >= 0)
{ dest [count] = src [count] ;
} ;
} /* i2f_array */
static inline void
d2f_array (const double *src, float *dest, int count)
{ while (--count >= 0)
{ dest [count] = src [count] ;
} ;
} /* d2f_array */
/*----------------------------------------------------------------------------------------------
*/
static sf_count_t
host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
float scale ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
/* Fix me : Need lef2s_array */
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
f2s_array (psf->u.fbuf, readcount, ptr + total, scale) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* host_read_f2s */
static sf_count_t
host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
float scale ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
f2i_array (psf->u.fbuf, readcount, ptr + total, scale) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* host_read_f2i */
static sf_count_t
host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
if (psf->float_endswap != SF_TRUE)
return psf_fread (ptr, sizeof (float), len, psf) ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
endswap_int_copy ((int*) (ptr + total), psf->u.ibuf, readcount) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* host_read_f */
static sf_count_t
host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
/* Fix me : Need lef2d_array */
f2d_array (psf->u.fbuf, readcount, ptr + total) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* host_read_f2d */
static sf_count_t
host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
s2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->peak_info)
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* host_write_s2f */
static sf_count_t
host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
i2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->peak_info)
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
writecount = psf_fwrite (psf->u.fbuf, sizeof (float) , bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* host_write_i2f */
static sf_count_t
host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
if (psf->peak_info)
float32_peak_update (psf, ptr, len, 0) ;
if (psf->float_endswap != SF_TRUE)
return psf_fwrite (ptr, sizeof (float), len, psf) ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
endswap_int_copy (psf->u.ibuf, (const int*) (ptr + total), bufferlen) ;
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* host_write_f */
static sf_count_t
host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
d2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->peak_info)
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* host_write_d2f */
/*=======================================================================================
*/
static sf_count_t
replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
float scale ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
bf2f_array (psf->u.fbuf, bufferlen) ;
f2s_array (psf->u.fbuf, readcount, ptr + total, scale) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* replace_read_f2s */
static sf_count_t
replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
float scale ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
bf2f_array (psf->u.fbuf, bufferlen) ;
f2i_array (psf->u.fbuf, readcount, ptr + total, scale) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* replace_read_f2i */
static sf_count_t
replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
/* FIX THIS */
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
bf2f_array (psf->u.fbuf, bufferlen) ;
memcpy (ptr + total, psf->u.fbuf, bufferlen * sizeof (float)) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* replace_read_f */
static sf_count_t
replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
bf2f_array (psf->u.fbuf, bufferlen) ;
f2d_array (psf->u.fbuf, readcount, ptr + total) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* replace_read_f2d */
static sf_count_t
replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
s2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->peak_info)
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
f2bf_array (psf->u.fbuf, bufferlen) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* replace_write_s2f */
static sf_count_t
replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
i2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->peak_info)
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
f2bf_array (psf->u.fbuf, bufferlen) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* replace_write_i2f */
static sf_count_t
replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
/* FIX THIS */
if (psf->peak_info)
float32_peak_update (psf, ptr, len, 0) ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
memcpy (psf->u.fbuf, ptr + total, bufferlen * sizeof (float)) ;
f2bf_array (psf->u.fbuf, bufferlen) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
writecount = psf_fwrite (psf->u.fbuf, sizeof (float) , bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* replace_write_f */
static sf_count_t
replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
d2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->peak_info)
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
f2bf_array (psf->u.fbuf, bufferlen) ;
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* replace_write_d2f */
/*----------------------------------------------------------------------------------------------
*/
static void
bf2f_array (float *buffer, int count)
{ while (--count >= 0)
{ buffer [count] = FLOAT32_READ ((unsigned char *) (buffer + count)) ;
} ;
} /* bf2f_array */
static void
f2bf_array (float *buffer, int count)
{ while (--count >= 0)
{ FLOAT32_WRITE (buffer [count], (unsigned char*) (buffer + count)) ;
} ;
} /* f2bf_array */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: b6c34917-488c-4145-9648-f4371fc4c889
*/

View File

@@ -0,0 +1,262 @@
/*
** Copyright (C) 2001-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Version 1.4 */
#ifndef FLOAT_CAST_HEADER
#define FLOAT_CAST_HEADER
/*============================================================================
** On Intel Pentium processors (especially PIII and probably P4), converting
** from float to int is very slow. To meet the C specs, the code produced by
** most C compilers targeting Pentium needs to change the FPU rounding mode
** before the float to int conversion is performed.
**
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
** is this flushing of the pipeline which is so slow.
**
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
** llrint and llrintf which fix this problem as a side effect.
**
** On Unix-like systems, the configure process should have detected the
** presence of these functions. If they weren't found we have to replace them
** here with a standard C cast.
*/
/*
** The C99 prototypes for lrint and lrintf are as follows:
**
** long int lrintf (float x) ;
** long int lrint (double x) ;
*/
#include "sfconfig.h"
/*
** The presence of the required functions are detected during the configure
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
** the sfconfig.h file.
*/
#define HAVE_LRINT_REPLACEMENT 0
#if (HAVE_LRINT && HAVE_LRINTF)
/*
** These defines enable functionality introduced with the 1999 ISO C
** standard. They must be defined before the inclusion of math.h to
** engage them. If optimisation is enabled, these functions will be
** inlined. With optimisation switched off, you have to link in the
** maths library using -lm.
*/
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
#elif (defined (__CYGWIN__))
#include <math.h>
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
/*
** The native CYGWIN lrint and lrintf functions are buggy:
** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
** and slow.
** These functions (pulled from the Public Domain MinGW math.h header)
** replace the native versions.
*/
static inline long double2int (double in)
{ long retval ;
__asm__ __volatile__
( "fistpl %0"
: "=m" (retval)
: "t" (in)
: "st"
) ;
return retval ;
} /* double2int */
static inline long float2int (float in)
{ long retval ;
__asm__ __volatile__
( "fistpl %0"
: "=m" (retval)
: "t" (in)
: "st"
) ;
return retval ;
} /* float2int */
#elif (defined (WIN32) || defined (_WIN32))
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
/*
** Win32 doesn't seem to have these functions.
** Therefore implement inline versions of these functions here.
*/
__inline long int
lrint (double flt)
{ int intgr ;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
__inline long int
lrintf (float flt)
{ int intgr ;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
#elif (defined (__MWERKS__) && defined (macintosh))
/* This MacOS 9 solution was provided by Stephane Letz */
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
inline int
float2int (register float in)
{ long res [2] ;
asm
{ fctiw in, in
stfd in, res
}
return res [1] ;
} /* float2int */
inline int
double2int (register double in)
{ long res [2] ;
asm
{ fctiw in, in
stfd in, res
}
return res [1] ;
} /* double2int */
#elif (defined (__MACH__) && defined (__APPLE__))
/* For Apple MacOSX. */
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
inline static long
float2int (register float in)
{ int res [2] ;
__asm__ __volatile__
( "fctiw %1, %1\n\t"
"stfd %1, %0"
: "=m" (res) /* Output */
: "f" (in) /* Input */
: "memory"
) ;
return res [1] ;
} /* lrintf */
inline static long
double2int (register double in)
{ int res [2] ;
__asm__ __volatile__
( "fctiw %1, %1\n\t"
"stfd %1, %0"
: "=m" (res) /* Output */
: "f" (in) /* Input */
: "memory"
) ;
return res [1] ;
} /* lrint */
#else
#ifndef __sgi
#warning "Don't have the functions lrint() and lrintf()."
#warning "Replacing these functions with a standard C cast."
#endif
#include <math.h>
#define lrint(dbl) ((long) (dbl))
#define lrintf(flt) ((long) (flt))
#endif
#endif /* FLOAT_CAST_HEADER */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 42db1693-ff61-4051-bac1-e4d24c4e30b7
*/

615
libs/libsndfile/src/g72x.c Normal file
View File

@@ -0,0 +1,615 @@
/*
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
#include "G72x/g72x.h"
/* This struct is private to the G72x code. */
struct g72x_state ;
typedef struct g72x_state G72x_STATE ;
typedef struct
{ /* Private data. Don't mess with it. */
struct g72x_state * private ;
/* Public data. Read only. */
int blocksize, samplesperblock, bytesperblock ;
/* Public data. Read and write. */
int blocks_total, block_curr, sample_curr ;
unsigned char block [G72x_BLOCK_SIZE] ;
short samples [G72x_BLOCK_SIZE] ;
} G72x_PRIVATE ;
static int psf_g72x_decode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) ;
static int psf_g72x_encode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) ;
static sf_count_t g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static sf_count_t g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int g72x_close (SF_PRIVATE *psf) ;
/*============================================================================================
** WAV G721 Reader initialisation function.
*/
int
g72x_init (SF_PRIVATE * psf)
{ G72x_PRIVATE *pg72x ;
int bitspersample, bytesperblock, codec ;
if (psf->fdata != NULL)
{ psf_log_printf (psf, "*** psf->fdata is not NULL.\n") ;
return SFE_INTERNAL ;
} ;
psf->sf.seekable = SF_FALSE ;
if (psf->sf.channels != 1)
return SFE_G72X_NOT_MONO ;
if ((pg72x = calloc (1, sizeof (G72x_PRIVATE))) == NULL)
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pg72x ;
pg72x->block_curr = 0 ;
pg72x->sample_curr = 0 ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_G721_32 :
codec = G721_32_BITS_PER_SAMPLE ;
bytesperblock = G721_32_BYTES_PER_BLOCK ;
bitspersample = G721_32_BITS_PER_SAMPLE ;
break ;
case SF_FORMAT_G723_24:
codec = G723_24_BITS_PER_SAMPLE ;
bytesperblock = G723_24_BYTES_PER_BLOCK ;
bitspersample = G723_24_BITS_PER_SAMPLE ;
break ;
case SF_FORMAT_G723_40:
codec = G723_40_BITS_PER_SAMPLE ;
bytesperblock = G723_40_BYTES_PER_BLOCK ;
bitspersample = G723_40_BITS_PER_SAMPLE ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
psf->blockwidth = psf->bytewidth = 1 ;
psf->filelength = psf_get_filelen (psf) ;
if (psf->filelength < psf->dataoffset)
psf->filelength = psf->dataoffset ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->dataend > 0)
psf->datalength -= psf->filelength - psf->dataend ;
if (psf->mode == SFM_READ)
{ pg72x->private = g72x_reader_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ;
if (pg72x->private == NULL)
return SFE_MALLOC_FAILED ;
pg72x->bytesperblock = bytesperblock ;
psf->read_short = g72x_read_s ;
psf->read_int = g72x_read_i ;
psf->read_float = g72x_read_f ;
psf->read_double = g72x_read_d ;
psf->seek = g72x_seek ;
if (psf->datalength % pg72x->blocksize)
{ psf_log_printf (psf, "*** Odd psf->datalength (%D) should be a multiple of %d\n", psf->datalength, pg72x->blocksize) ;
pg72x->blocks_total = (psf->datalength / pg72x->blocksize) + 1 ;
}
else
pg72x->blocks_total = psf->datalength / pg72x->blocksize ;
psf->sf.frames = pg72x->blocks_total * pg72x->samplesperblock ;
psf_g72x_decode_block (psf, pg72x) ;
}
else if (psf->mode == SFM_WRITE)
{ pg72x->private = g72x_writer_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ;
if (pg72x->private == NULL)
return SFE_MALLOC_FAILED ;
pg72x->bytesperblock = bytesperblock ;
psf->write_short = g72x_write_s ;
psf->write_int = g72x_write_i ;
psf->write_float = g72x_write_f ;
psf->write_double = g72x_write_d ;
if (psf->datalength % pg72x->blocksize)
pg72x->blocks_total = (psf->datalength / pg72x->blocksize) + 1 ;
else
pg72x->blocks_total = psf->datalength / pg72x->blocksize ;
if (psf->datalength > 0)
psf->sf.frames = (8 * psf->datalength) / bitspersample ;
if ((psf->sf.frames * bitspersample) / 8 != psf->datalength)
psf_log_printf (psf, "*** Warning : weird psf->datalength.\n") ;
} ;
psf->codec_close = g72x_close ;
return 0 ;
} /* g72x_init */
/*============================================================================================
** G721 Read Functions.
*/
static int
psf_g72x_decode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x)
{ int k ;
pg72x->block_curr ++ ;
pg72x->sample_curr = 0 ;
if (pg72x->block_curr > pg72x->blocks_total)
{ memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ;
return 1 ;
} ;
if ((k = psf_fread (pg72x->block, 1, pg72x->bytesperblock, psf)) != pg72x->bytesperblock)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pg72x->bytesperblock) ;
pg72x->blocksize = k ;
g72x_decode_block (pg72x->private, pg72x->block, pg72x->samples) ;
return 1 ;
} /* psf_g72x_decode_block */
static int
g72x_read_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x, short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ if (pg72x->block_curr > pg72x->blocks_total)
{ memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
return total ;
} ;
if (pg72x->sample_curr >= pg72x->samplesperblock)
psf_g72x_decode_block (psf, pg72x) ;
count = pg72x->samplesperblock - pg72x->sample_curr ;
count = (len - indx > count) ? count : len - indx ;
memcpy (&(ptr [indx]), &(pg72x->samples [pg72x->sample_curr]), count * sizeof (short)) ;
indx += count ;
pg72x->sample_curr += count ;
total = indx ;
} ;
return total ;
} /* g72x_read_block */
static sf_count_t
g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ G72x_PRIVATE *pg72x ;
int readcount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
while (len > 0)
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = g72x_read_block (psf, pg72x, ptr, readcount) ;
total += count ;
len -= count ;
if (count != readcount)
break ;
} ;
return total ;
} /* g72x_read_s */
static sf_count_t
g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ G72x_PRIVATE *pg72x ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = sptr [k] << 16 ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* g72x_read_i */
static sf_count_t
g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ G72x_PRIVATE *pg72x ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * sptr [k] ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* g72x_read_f */
static sf_count_t
g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ G72x_PRIVATE *pg72x ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (double) (sptr [k]) ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* g72x_read_d */
static sf_count_t
g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{
/* Prevent compiler warnings. */
mode ++ ;
offset ++ ;
psf_log_printf (psf, "seek unsupported\n") ;
/* No simple solution. To do properly, would need to seek
** to start of file and decode everything up to seek position.
** Maybe implement SEEK_SET to 0 only?
*/
return 0 ;
/*
** G72x_PRIVATE *pg72x ;
** int newblock, newsample, sample_curr ;
**
** if (psf->fdata == NULL)
** return 0 ;
** pg72x = (G72x_PRIVATE*) psf->fdata ;
**
** if (! (psf->datalength && psf->dataoffset))
** { psf->error = SFE_BAD_SEEK ;
** return PSF_SEEK_ERROR ;
** } ;
**
** sample_curr = (8 * psf->datalength) / G721_32_BITS_PER_SAMPLE ;
**
** switch (whence)
** { case SEEK_SET :
** if (offset < 0 || offset > sample_curr)
** { psf->error = SFE_BAD_SEEK ;
** return PSF_SEEK_ERROR ;
** } ;
** newblock = offset / pg72x->samplesperblock ;
** newsample = offset % pg72x->samplesperblock ;
** break ;
**
** case SEEK_CUR :
** if (psf->current + offset < 0 || psf->current + offset > sample_curr)
** { psf->error = SFE_BAD_SEEK ;
** return PSF_SEEK_ERROR ;
** } ;
** newblock = (8 * (psf->current + offset)) / pg72x->samplesperblock ;
** newsample = (8 * (psf->current + offset)) % pg72x->samplesperblock ;
** break ;
**
** case SEEK_END :
** if (offset > 0 || sample_curr + offset < 0)
** { psf->error = SFE_BAD_SEEK ;
** return PSF_SEEK_ERROR ;
** } ;
** newblock = (sample_curr + offset) / pg72x->samplesperblock ;
** newsample = (sample_curr + offset) % pg72x->samplesperblock ;
** break ;
**
** default :
** psf->error = SFE_BAD_SEEK ;
** return PSF_SEEK_ERROR ;
** } ;
**
** if (psf->mode == SFM_READ)
** { psf_fseek (psf, psf->dataoffset + newblock * pg72x->blocksize, SEEK_SET) ;
** pg72x->block_curr = newblock ;
** psf_g72x_decode_block (psf, pg72x) ;
** pg72x->sample_curr = newsample ;
** }
** else
** { /+* What to do about write??? *+/
** psf->error = SFE_BAD_SEEK ;
** return PSF_SEEK_ERROR ;
** } ;
**
** psf->current = newblock * pg72x->samplesperblock + newsample ;
** return psf->current ;
**
*/
} /* g72x_seek */
/*==========================================================================================
** G72x Write Functions.
*/
static int
psf_g72x_encode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x)
{ int k ;
/* Encode the samples. */
g72x_encode_block (pg72x->private, pg72x->samples, pg72x->block) ;
/* Write the block to disk. */
if ((k = psf_fwrite (pg72x->block, 1, pg72x->blocksize, psf)) != pg72x->blocksize)
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pg72x->blocksize) ;
pg72x->sample_curr = 0 ;
pg72x->block_curr ++ ;
/* Set samples to zero for next block. */
memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ;
return 1 ;
} /* psf_g72x_encode_block */
static int
g72x_write_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x, const short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ count = pg72x->samplesperblock - pg72x->sample_curr ;
if (count > len - indx)
count = len - indx ;
memcpy (&(pg72x->samples [pg72x->sample_curr]), &(ptr [indx]), count * sizeof (short)) ;
indx += count ;
pg72x->sample_curr += count ;
total = indx ;
if (pg72x->sample_curr >= pg72x->samplesperblock)
psf_g72x_encode_block (psf, pg72x) ;
} ;
return total ;
} /* g72x_write_block */
static sf_count_t
g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ G72x_PRIVATE *pg72x ;
int writecount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
while (len > 0)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = g72x_write_block (psf, pg72x, ptr, writecount) ;
total += count ;
len -= count ;
if (count != writecount)
break ;
} ;
return total ;
} /* g72x_write_s */
static sf_count_t
g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ G72x_PRIVATE *pg72x ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = ptr [total + k] >> 16 ;
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* g72x_write_i */
static sf_count_t
g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ G72x_PRIVATE *pg72x ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = lrintf (normfact * ptr [total + k]) ;
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* g72x_write_f */
static sf_count_t
g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ G72x_PRIVATE *pg72x ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = lrint (normfact * ptr [total + k]) ;
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* g72x_write_d */
static int
g72x_close (SF_PRIVATE *psf)
{ G72x_PRIVATE *pg72x ;
pg72x = (G72x_PRIVATE*) psf->fdata ;
if (psf->mode == SFM_WRITE)
{ /* If a block has been partially assembled, write it out
** as the final block.
*/
if (pg72x->sample_curr && pg72x->sample_curr < G72x_BLOCK_SIZE)
psf_g72x_encode_block (psf, pg72x) ;
if (psf->write_header)
psf->write_header (psf, SF_FALSE) ;
} ;
/* Only free the pointer allocated by g72x_(reader|writer)_init. */
free (pg72x->private) ;
return 0 ;
} /* g72x_close */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 3cc5439e-7247-486b-b2e6-11a4affa5744
*/

View File

@@ -0,0 +1,628 @@
/*
** Copyright (C) 1999-2006 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
#include "wav_w64.h"
#include "GSM610/gsm.h"
#define GSM610_BLOCKSIZE 33
#define GSM610_SAMPLES 160
typedef struct gsm610_tag
{ int blocks ;
int blockcount, samplecount ;
int samplesperblock, blocksize ;
int (*decode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ;
int (*encode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ;
short samples [WAV_W64_GSM610_SAMPLES] ;
unsigned char block [WAV_W64_GSM610_BLOCKSIZE] ;
/* Damn I hate typedef-ed pointers; yes, gsm is a pointer type. */
gsm gsm_data ;
} GSM610_PRIVATE ;
static sf_count_t gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static int gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) ;
static int gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len) ;
static int gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
static int gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
static int gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
static int gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
static sf_count_t gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int gsm610_close (SF_PRIVATE *psf) ;
/*============================================================================================
** WAV GSM610 initialisation function.
*/
int
gsm610_init (SF_PRIVATE *psf)
{ GSM610_PRIVATE *pgsm610 ;
int true_flag = 1 ;
if (psf->fdata != NULL)
{ psf_log_printf (psf, "*** psf->fdata is not NULL.\n") ;
return SFE_INTERNAL ;
} ;
if (psf->mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
psf->sf.seekable = SF_FALSE ;
if ((pgsm610 = calloc (1, sizeof (GSM610_PRIVATE))) == NULL)
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pgsm610 ;
memset (pgsm610, 0, sizeof (GSM610_PRIVATE)) ;
/*============================================================
Need separate gsm_data structs for encode and decode.
============================================================*/
if ((pgsm610->gsm_data = gsm_create ()) == NULL)
return SFE_MALLOC_FAILED ;
switch (psf->sf.format & SF_FORMAT_TYPEMASK)
{ case SF_FORMAT_WAV :
case SF_FORMAT_WAVEX :
case SF_FORMAT_W64 :
gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ;
pgsm610->encode_block = gsm610_wav_encode_block ;
pgsm610->decode_block = gsm610_wav_decode_block ;
pgsm610->samplesperblock = WAV_W64_GSM610_SAMPLES ;
pgsm610->blocksize = WAV_W64_GSM610_BLOCKSIZE ;
break ;
case SF_FORMAT_AIFF :
case SF_FORMAT_RAW :
pgsm610->encode_block = gsm610_encode_block ;
pgsm610->decode_block = gsm610_decode_block ;
pgsm610->samplesperblock = GSM610_SAMPLES ;
pgsm610->blocksize = GSM610_BLOCKSIZE ;
break ;
default :
return SFE_INTERNAL ;
break ;
} ;
if (psf->mode == SFM_READ)
{ if (psf->datalength % pgsm610->blocksize == 0)
pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
else if (psf->datalength % pgsm610->blocksize == 1 && pgsm610->blocksize == GSM610_BLOCKSIZE)
{ /*
** Weird AIFF specific case.
** AIFF chunks must be at an odd offset from the start of file and
** GSM610_BLOCKSIZE is odd which can result in an odd length SSND
** chunk. The SSND chunk then gets padded on write which means that
** when it is read the datalength is too big by 1.
*/
pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
}
else
{ psf_log_printf (psf, "*** Warning : data chunk seems to be truncated.\n") ;
pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ;
} ;
psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ;
pgsm610->decode_block (psf, pgsm610) ; /* Read first block. */
psf->read_short = gsm610_read_s ;
psf->read_int = gsm610_read_i ;
psf->read_float = gsm610_read_f ;
psf->read_double = gsm610_read_d ;
} ;
if (psf->mode == SFM_WRITE)
{ pgsm610->blockcount = 0 ;
pgsm610->samplecount = 0 ;
psf->write_short = gsm610_write_s ;
psf->write_int = gsm610_write_i ;
psf->write_float = gsm610_write_f ;
psf->write_double = gsm610_write_d ;
} ;
psf->codec_close = gsm610_close ;
psf->seek = gsm610_seek ;
psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
return 0 ;
} /* gsm610_init */
/*============================================================================================
** GSM 6.10 Read Functions.
*/
static int
gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
{ int k ;
pgsm610->blockcount ++ ;
pgsm610->samplecount = 0 ;
if (pgsm610->blockcount > pgsm610->blocks)
{ memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
return 1 ;
} ;
if ((k = psf_fread (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ;
if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
{ psf_log_printf (psf, "Error from gsm_decode() on frame : %d\n", pgsm610->blockcount) ;
return 0 ;
} ;
if (gsm_decode (pgsm610->gsm_data, pgsm610->block + (WAV_W64_GSM610_BLOCKSIZE + 1) / 2, pgsm610->samples + WAV_W64_GSM610_SAMPLES / 2) < 0)
{ psf_log_printf (psf, "Error from gsm_decode() on frame : %d.5\n", pgsm610->blockcount) ;
return 0 ;
} ;
return 1 ;
} /* gsm610_wav_decode_block */
static int
gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
{ int k ;
pgsm610->blockcount ++ ;
pgsm610->samplecount = 0 ;
if (pgsm610->blockcount > pgsm610->blocks)
{ memset (pgsm610->samples, 0, GSM610_SAMPLES * sizeof (short)) ;
return 1 ;
} ;
if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
{ psf_log_printf (psf, "Error from gsm_decode() on frame : %d\n", pgsm610->blockcount) ;
return 0 ;
} ;
return 1 ;
} /* gsm610_decode_block */
static int
gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ if (pgsm610->blockcount >= pgsm610->blocks && pgsm610->samplecount >= pgsm610->samplesperblock)
{ memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
return total ;
} ;
if (pgsm610->samplecount >= pgsm610->samplesperblock)
pgsm610->decode_block (psf, pgsm610) ;
count = pgsm610->samplesperblock - pgsm610->samplecount ;
count = (len - indx > count) ? count : len - indx ;
memcpy (&(ptr [indx]), &(pgsm610->samples [pgsm610->samplecount]), count * sizeof (short)) ;
indx += count ;
pgsm610->samplecount += count ;
total = indx ;
} ;
return total ;
} /* gsm610_read_block */
static sf_count_t
gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
int readcount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
while (len > 0)
{ readcount = (len > 0x10000000) ? 0x1000000 : (int) len ;
count = gsm610_read_block (psf, pgsm610, ptr, readcount) ;
total += count ;
len -= count ;
if (count != readcount)
break ;
} ;
return total ;
} /* gsm610_read_s */
static sf_count_t
gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = sptr [k] << 16 ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* gsm610_read_i */
static sf_count_t
gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * sptr [k] ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* gsm610_read_f */
static sf_count_t
gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * sptr [k] ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* gsm610_read_d */
static sf_count_t
gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{ GSM610_PRIVATE *pgsm610 ;
int newblock, newsample ;
mode = mode ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
if (psf->dataoffset < 0)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
if (offset == 0)
{ int true_flag = 1 ;
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
pgsm610->blockcount = 0 ;
gsm_init (pgsm610->gsm_data) ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV ||
(psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_W64)
gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ;
pgsm610->decode_block (psf, pgsm610) ;
pgsm610->samplecount = 0 ;
return 0 ;
} ;
if (offset < 0 || offset > pgsm610->blocks * pgsm610->samplesperblock)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
newblock = offset / pgsm610->samplesperblock ;
newsample = offset % pgsm610->samplesperblock ;
if (psf->mode == SFM_READ)
{ if (psf->read_current != newblock * pgsm610->samplesperblock + newsample)
{ psf_fseek (psf, psf->dataoffset + newblock * pgsm610->samplesperblock, SEEK_SET) ;
pgsm610->blockcount = newblock ;
pgsm610->decode_block (psf, pgsm610) ;
pgsm610->samplecount = newsample ;
} ;
return newblock * pgsm610->samplesperblock + newsample ;
} ;
/* What to do about write??? */
psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} /* gsm610_seek */
/*==========================================================================================
** GSM 6.10 Write Functions.
*/
static int
gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
{ int k ;
/* Encode the samples. */
gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
/* Write the block to disk. */
if ((k = psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
pgsm610->samplecount = 0 ;
pgsm610->blockcount ++ ;
/* Set samples to zero for next block. */
memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
return 1 ;
} /* gsm610_encode_block */
static int
gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
{ int k ;
/* Encode the samples. */
gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAV_W64_GSM610_SAMPLES/2, pgsm610->block+WAV_W64_GSM610_BLOCKSIZE/2) ;
/* Write the block to disk. */
if ((k = psf_fwrite (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE)
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ;
pgsm610->samplecount = 0 ;
pgsm610->blockcount ++ ;
/* Set samples to zero for next block. */
memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
return 1 ;
} /* gsm610_wav_encode_block */
static int
gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ count = pgsm610->samplesperblock - pgsm610->samplecount ;
if (count > len - indx)
count = len - indx ;
memcpy (&(pgsm610->samples [pgsm610->samplecount]), &(ptr [indx]), count * sizeof (short)) ;
indx += count ;
pgsm610->samplecount += count ;
total = indx ;
if (pgsm610->samplecount >= pgsm610->samplesperblock)
pgsm610->encode_block (psf, pgsm610) ;
} ;
return total ;
} /* gsm610_write_block */
static sf_count_t
gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
int writecount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
while (len > 0)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = gsm610_write_block (psf, pgsm610, ptr, writecount) ;
total += count ;
len -= count ;
if (count != writecount)
break ;
} ;
return total ;
} /* gsm610_write_s */
static sf_count_t
gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = ptr [total + k] >> 16 ;
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* gsm610_write_i */
static sf_count_t
gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = lrintf (normfact * ptr [total + k]) ;
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* gsm610_write_f */
static sf_count_t
gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = lrint (normfact * ptr [total + k]) ;
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* gsm610_write_d */
static int
gsm610_close (SF_PRIVATE *psf)
{ GSM610_PRIVATE *pgsm610 ;
if (psf->fdata == NULL)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
if (psf->mode == SFM_WRITE)
{ /* If a block has been partially assembled, write it out
** as the final block.
*/
if (pgsm610->samplecount && pgsm610->samplecount < pgsm610->samplesperblock)
pgsm610->encode_block (psf, pgsm610) ;
} ;
if (pgsm610->gsm_data)
gsm_destroy (pgsm610->gsm_data) ;
return 0 ;
} /* gsm610_close */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 8575187d-af4f-4acf-b9dd-6ff705628345
*/

225
libs/libsndfile/src/htk.c Normal file
View File

@@ -0,0 +1,225 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define SFE_HTK_BAD_FILE_LEN 1666
#define SFE_HTK_NOT_WAVEFORM 1667
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int htk_close (SF_PRIVATE *psf) ;
static int htk_write_header (SF_PRIVATE *psf, int calc_length) ;
static int htk_read_header (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
htk_open (SF_PRIVATE *psf)
{ int subformat ;
int error = 0 ;
if (psf->is_pipe)
return SFE_HTK_NO_PIPE ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = htk_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_HTK)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = SF_ENDIAN_BIG ;
if (htk_write_header (psf, SF_FALSE))
return psf->error ;
psf->write_header = htk_write_header ;
} ;
psf->container_close = htk_close ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
switch (subformat)
{ case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
error = pcm_init (psf) ;
break ;
default : break ;
} ;
return error ;
} /* htk_open */
/*------------------------------------------------------------------------------
*/
static int
htk_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
htk_write_header (psf, SF_TRUE) ;
return 0 ;
} /* htk_close */
static int
htk_write_header (SF_PRIVATE *psf, int calc_length)
{ sf_count_t current ;
int sample_count, sample_period ;
current = psf_ftell (psf) ;
if (calc_length)
psf->filelength = psf_get_filelen (psf) ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
psf_fseek (psf, 0, SEEK_SET) ;
if (psf->filelength > 12)
sample_count = (psf->filelength - 12) / 2 ;
else
sample_count = 0 ;
sample_period = 10000000 / psf->sf.samplerate ;
psf_binheader_writef (psf, "E444", sample_count, sample_period, 0x20000) ;
/* Header construction complete so write it out. */
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* htk_write_header */
/*
** Found the following info in a comment block within Bill Schottstaedt's
** sndlib library.
**
** HTK format files consist of a contiguous sequence of samples preceded by a
** header. Each sample is a vector of either 2-byte integers or 4-byte floats.
** 2-byte integers are used for compressed forms as described below and for
** vector quantised data as described later in section 5.11. HTK format data
** files can also be used to store speech waveforms as described in section 5.8.
**
** The HTK file format header is 12 bytes long and contains the following data
** nSamples -- number of samples in file (4-byte integer)
** sampPeriod -- sample period in 100ns units (4-byte integer)
** sampSize -- number of bytes per sample (2-byte integer)
** parmKind -- a code indicating the sample kind (2-byte integer)
**
** The parameter kind consists of a 6 bit code representing the basic
** parameter kind plus additional bits for each of the possible qualifiers.
** The basic parameter kind codes are
**
** 0 WAVEFORM sampled waveform
** 1 LPC linear prediction filter coefficients
** 2 LPREFC linear prediction reflection coefficients
** 3 LPCEPSTRA LPC cepstral coefficients
** 4 LPDELCEP LPC cepstra plus delta coefficients
** 5 IREFC LPC reflection coef in 16 bit integer format
** 6 MFCC mel-frequency cepstral coefficients
** 7 FBANK log mel-filter bank channel outputs
** 8 MELSPEC linear mel-filter bank channel outputs
** 9 USER user defined sample kind
** 10 DISCRETE vector quantised data
**
** and the bit-encoding for the qualifiers (in octal) is
** _E 000100 has energy
** _N 000200 absolute energy suppressed
** _D 000400 has delta coefficients
** _A 001000 has acceleration coefficients
** _C 002000 is compressed
** _Z 004000 has zero mean static coef.
** _K 010000 has CRC checksum
** _O 020000 has 0'th cepstral coef.
*/
static int
htk_read_header (SF_PRIVATE *psf)
{ int sample_count, sample_period, marker ;
psf_binheader_readf (psf, "pE444", 0, &sample_count, &sample_period, &marker) ;
if (2 * sample_count + 12 != psf->filelength)
return SFE_HTK_BAD_FILE_LEN ;
if (marker != 0x20000)
return SFE_HTK_NOT_WAVEFORM ;
psf->sf.channels = 1 ;
psf->sf.samplerate = 10000000 / sample_period ;
psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d => %d Hz\n",
sample_count, sample_period, psf->sf.samplerate) ;
psf->sf.format = SF_FORMAT_HTK | SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
/* HTK always has a 12 byte header. */
psf->dataoffset = 12 ;
psf->endian = SF_ENDIAN_BIG ;
psf->datalength = psf->filelength - psf->dataoffset ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
if (! psf->sf.frames && psf->blockwidth)
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
return 0 ;
} /* htk_read_header */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: c350e972-082e-4c20-8934-03391a723560
*/

View File

@@ -0,0 +1,976 @@
/*
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
typedef struct IMA_ADPCM_PRIVATE_tag
{ int (*decode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ;
int (*encode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ;
int channels, blocksize, samplesperblock, blocks ;
int blockcount, samplecount ;
int previous [2] ;
int stepindx [2] ;
unsigned char *block ;
short *samples ;
#if HAVE_FLEXIBLE_ARRAY
short data [] ; /* ISO C99 struct flexible array. */
#else
short data [0] ; /* This is a hack and might not work. */
#endif
} IMA_ADPCM_PRIVATE ;
/*============================================================================================
** Predefined IMA ADPCM data.
*/
static int ima_indx_adjust [16] =
{ -1, -1, -1, -1, /* +0 - +3, decrease the step size */
2, 4, 6, 8, /* +4 - +7, increase the step size */
-1, -1, -1, -1, /* -0 - -3, decrease the step size */
2, 4, 6, 8, /* -4 - -7, increase the step size */
} ;
static int ima_step_size [89] =
{ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230,
253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767
} ;
static int ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
static int ima_writer_init (SF_PRIVATE *psf, int blockalign) ;
static int ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) ;
static int ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len) ;
static sf_count_t ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static sf_count_t ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int ima_close (SF_PRIVATE *psf) ;
static int wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
static int wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
/*-static int aiff_ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;-*/
static int aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
static int aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
/*============================================================================================
** IMA ADPCM Reader initialisation function.
*/
int
wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
{ int error ;
if (psf->fdata != NULL)
{ psf_log_printf (psf, "*** psf->fdata is not NULL.\n") ;
return SFE_INTERNAL ;
} ;
if (psf->mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
if (psf->mode == SFM_READ)
if ((error = ima_reader_init (psf, blockalign, samplesperblock)))
return error ;
if (psf->mode == SFM_WRITE)
if ((error = ima_writer_init (psf, blockalign)))
return error ;
psf->codec_close = ima_close ;
psf->seek = ima_seek ;
return 0 ;
} /* wav_w64_ima_init */
int
aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
{ int error ;
if (psf->mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
if (psf->mode == SFM_READ)
if ((error = ima_reader_init (psf, blockalign, samplesperblock)))
return error ;
if (psf->mode == SFM_WRITE)
if ((error = ima_writer_init (psf, blockalign)))
return error ;
psf->codec_close = ima_close ;
return 0 ;
} /* aiff_ima_init */
static int
ima_close (SF_PRIVATE *psf)
{ IMA_ADPCM_PRIVATE *pima ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
if (psf->mode == SFM_WRITE)
{ /* If a block has been partially assembled, write it out
** as the final block.
*/
if (pima->samplecount && pima->samplecount < pima->samplesperblock)
pima->encode_block (psf, pima) ;
psf->sf.frames = pima->samplesperblock * pima->blockcount / psf->sf.channels ;
} ;
return 0 ;
} /* ima_close */
/*============================================================================================
** IMA ADPCM Read Functions.
*/
static int
ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
{ IMA_ADPCM_PRIVATE *pima ;
int pimasize, count ;
if (psf->mode != SFM_READ)
return SFE_BAD_MODE_RW ;
pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ;
if (! (pima = malloc (pimasize)))
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pima ;
memset (pima, 0, pimasize) ;
pima->samples = pima->data ;
pima->block = (unsigned char*) (pima->data + samplesperblock * psf->sf.channels) ;
pima->channels = psf->sf.channels ;
pima->blocksize = blockalign ;
pima->samplesperblock = samplesperblock ;
psf->filelength = psf_get_filelen (psf) ;
psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset :
psf->filelength - psf->dataoffset ;
if (psf->datalength % pima->blocksize)
pima->blocks = psf->datalength / pima->blocksize + 1 ;
else
pima->blocks = psf->datalength / pima->blocksize ;
switch (psf->sf.format & SF_FORMAT_TYPEMASK)
{ case SF_FORMAT_WAV :
case SF_FORMAT_W64 :
count = 2 * (pima->blocksize - 4 * pima->channels) / pima->channels + 1 ;
if (pima->samplesperblock != count)
psf_log_printf (psf, "*** Warning : samplesperblock should be %d.\n", count) ;
pima->decode_block = wav_w64_ima_decode_block ;
psf->sf.frames = pima->samplesperblock * pima->blocks ;
break ;
case SF_FORMAT_AIFF :
psf_log_printf (psf, "still need to check block count\n") ;
pima->decode_block = aiff_ima_decode_block ;
psf->sf.frames = pima->samplesperblock * pima->blocks / pima->channels ;
break ;
default :
psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
return SFE_INTERNAL ;
break ;
} ;
pima->decode_block (psf, pima) ; /* Read first block. */
psf->read_short = ima_read_s ;
psf->read_int = ima_read_i ;
psf->read_float = ima_read_f ;
psf->read_double = ima_read_d ;
return 0 ;
} /* ima_reader_init */
static int
aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
{ unsigned char *blockdata ;
int chan, k, diff, bytecode ;
short step, stepindx, predictor, *sampledata ;
static int count = 0 ;
count ++ ;
pima->blockcount += pima->channels ;
pima->samplecount = 0 ;
if (pima->blockcount > pima->blocks)
{ memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ;
return 1 ;
} ;
if ((k = psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
/* Read and check the block header. */
for (chan = 0 ; chan < pima->channels ; chan++)
{ blockdata = pima->block + chan * 34 ;
sampledata = pima->samples + chan ;
predictor = (blockdata [0] << 8) | (blockdata [1] & 0x80) ;
stepindx = blockdata [1] & 0x7F ;
{
if (count < 5)
printf ("\nchan: %d predictor: %d stepindx: %d (%d)\n",
chan, predictor, stepindx, ima_step_size [stepindx]) ;
}
/* FIXME : Do this a better way. */
if (stepindx < 0) stepindx = 0 ;
else if (stepindx > 88) stepindx = 88 ;
/*
** Pull apart the packed 4 bit samples and store them in their
** correct sample positions.
*/
for (k = 0 ; k < pima->blocksize - 2 ; k++)
{ bytecode = blockdata [k + 2] ;
sampledata [pima->channels * (2 * k + 0)] = bytecode & 0xF ;
sampledata [pima->channels * (2 * k + 1)] = (bytecode >> 4) & 0xF ;
} ;
/* Decode the encoded 4 bit samples. */
for (k = 0 ; k < pima->samplesperblock ; k ++)
{ step = ima_step_size [stepindx] ;
bytecode = pima->samples [pima->channels * k + chan] ;
stepindx += ima_indx_adjust [bytecode] ;
if (stepindx < 0) stepindx = 0 ;
else if (stepindx > 88) stepindx = 88 ;
diff = step >> 3 ;
if (bytecode & 1) diff += step >> 2 ;
if (bytecode & 2) diff += step >> 1 ;
if (bytecode & 4) diff += step ;
if (bytecode & 8) diff = -diff ;
predictor += diff ;
pima->samples [pima->channels * k + chan] = predictor ;
} ;
} ;
if (count < 5)
{
for (k = 0 ; k < 10 ; k++)
printf ("% 7d,", pima->samples [k]) ;
puts ("") ;
}
return 1 ;
} /* aiff_ima_decode_block */
static int
aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
{ int chan, k, step, diff, vpdiff, blockindx, indx ;
short bytecode, mask ;
static int count = 0 ;
if (0 && count == 0)
{ pima->samples [0] = 0 ;
printf ("blocksize : %d\n", pima->blocksize) ;
printf ("pima->stepindx [0] : %d\n", pima->stepindx [0]) ;
}
count ++ ;
/* Encode the block header. */
for (chan = 0 ; chan < pima->channels ; chan ++)
{ blockindx = chan * pima->blocksize ;
pima->block [blockindx] = (pima->samples [chan] >> 8) & 0xFF ;
pima->block [blockindx + 1] = (pima->samples [chan] & 0x80) + (pima->stepindx [chan] & 0x7F) ;
pima->previous [chan] = pima->samples [chan] ;
} ;
/* Encode second and later samples for every block as a 4 bit value. */
for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
{ chan = (pima->channels > 1) ? (k % 2) : 0 ;
diff = pima->samples [k] - pima->previous [chan] ;
bytecode = 0 ;
step = ima_step_size [pima->stepindx [chan]] ;
vpdiff = step >> 3 ;
if (diff < 0)
{ bytecode = 8 ;
diff = -diff ;
} ;
mask = 4 ;
while (mask)
{ if (diff >= step)
{ bytecode |= mask ;
diff -= step ;
vpdiff += step ;
} ;
step >>= 1 ;
mask >>= 1 ;
} ;
if (bytecode & 8)
pima->previous [chan] -= vpdiff ;
else
pima->previous [chan] += vpdiff ;
if (pima->previous [chan] > 32767)
pima->previous [chan] = 32767 ;
else if (pima->previous [chan] < -32768)
pima->previous [chan] = -32768 ;
pima->stepindx [chan] += ima_indx_adjust [bytecode] ;
if (pima->stepindx [chan] < 0)
pima->stepindx [chan] = 0 ;
else if (pima->stepindx [chan] > 88)
pima->stepindx [chan] = 88 ;
pima->samples [k] = bytecode ;
} ;
/* Pack the 4 bit encoded samples. */
for (chan = 0 ; chan < pima->channels ; chan ++)
{ for (indx = pima->channels ; indx < pima->channels * pima->samplesperblock ; indx += 2 * pima->channels)
{ blockindx = chan * pima->blocksize + 2 + indx / 2 ;
if (0 && count ++ < 5)
printf ("chan: %d blockindx: %3d indx: %3d\n", chan, blockindx, indx) ;
pima->block [blockindx] = pima->samples [indx] & 0x0F ;
pima->block [blockindx] |= (pima->samples [indx + pima->channels] << 4) & 0xF0 ;
} ;
} ;
/* Write the block to disk. */
if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize)
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ;
memset (pima->samples, 0, pima->channels * pima->samplesperblock * sizeof (short)) ;
pima->samplecount = 0 ;
pima->blockcount ++ ;
return 1 ;
} /* aiff_ima_encode_block */
static int
wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
{ int chan, k, current, blockindx, indx, indxstart, diff ;
short step, bytecode, stepindx [2] ;
pima->blockcount ++ ;
pima->samplecount = 0 ;
if (pima->blockcount > pima->blocks)
{ memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ;
return 1 ;
} ;
if ((k = psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
/* Read and check the block header. */
for (chan = 0 ; chan < pima->channels ; chan++)
{ current = pima->block [chan*4] | (pima->block [chan*4+1] << 8) ;
if (current & 0x8000)
current -= 0x10000 ;
stepindx [chan] = pima->block [chan*4+2] ;
if (stepindx [chan] < 0)
stepindx [chan] = 0 ;
else if (stepindx [chan] > 88)
stepindx [chan] = 88 ;
if (pima->block [chan*4+3] != 0)
psf_log_printf (psf, "IMA ADPCM synchronisation error.\n") ;
pima->samples [chan] = current ;
} ;
/*
** Pull apart the packed 4 bit samples and store them in their
** correct sample positions.
*/
blockindx = 4 * pima->channels ;
indxstart = pima->channels ;
while (blockindx < pima->blocksize)
{ for (chan = 0 ; chan < pima->channels ; chan++)
{ indx = indxstart + chan ;
for (k = 0 ; k < 4 ; k++)
{ bytecode = pima->block [blockindx++] ;
pima->samples [indx] = bytecode & 0x0F ;
indx += pima->channels ;
pima->samples [indx] = (bytecode >> 4) & 0x0F ;
indx += pima->channels ;
} ;
} ;
indxstart += 8 * pima->channels ;
} ;
/* Decode the encoded 4 bit samples. */
for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
{ chan = (pima->channels > 1) ? (k % 2) : 0 ;
bytecode = pima->samples [k] & 0xF ;
step = ima_step_size [stepindx [chan]] ;
current = pima->samples [k - pima->channels] ;
diff = step >> 3 ;
if (bytecode & 1)
diff += step >> 2 ;
if (bytecode & 2)
diff += step >> 1 ;
if (bytecode & 4)
diff += step ;
if (bytecode & 8)
diff = -diff ;
current += diff ;
if (current > 32767)
current = 32767 ;
else if (current < -32768)
current = -32768 ;
stepindx [chan] += ima_indx_adjust [bytecode] ;
if (stepindx [chan] < 0)
stepindx [chan] = 0 ;
else if (stepindx [chan] > 88)
stepindx [chan] = 88 ;
pima->samples [k] = current ;
} ;
return 1 ;
} /* wav_w64_ima_decode_block */
static int
wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
{ int chan, k, step, diff, vpdiff, blockindx, indx, indxstart ;
short bytecode, mask ;
/* Encode the block header. */
for (chan = 0 ; chan < pima->channels ; chan++)
{ pima->block [chan*4] = pima->samples [chan] & 0xFF ;
pima->block [chan*4+1] = (pima->samples [chan] >> 8) & 0xFF ;
pima->block [chan*4+2] = pima->stepindx [chan] ;
pima->block [chan*4+3] = 0 ;
pima->previous [chan] = pima->samples [chan] ;
} ;
/* Encode the samples as 4 bit. */
for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
{ chan = (pima->channels > 1) ? (k % 2) : 0 ;
diff = pima->samples [k] - pima->previous [chan] ;
bytecode = 0 ;
step = ima_step_size [pima->stepindx [chan]] ;
vpdiff = step >> 3 ;
if (diff < 0)
{ bytecode = 8 ;
diff = -diff ;
} ;
mask = 4 ;
while (mask)
{ if (diff >= step)
{ bytecode |= mask ;
diff -= step ;
vpdiff += step ;
} ;
step >>= 1 ;
mask >>= 1 ;
} ;
if (bytecode & 8)
pima->previous [chan] -= vpdiff ;
else
pima->previous [chan] += vpdiff ;
if (pima->previous [chan] > 32767)
pima->previous [chan] = 32767 ;
else if (pima->previous [chan] < -32768)
pima->previous [chan] = -32768 ;
pima->stepindx [chan] += ima_indx_adjust [bytecode] ;
if (pima->stepindx [chan] < 0)
pima->stepindx [chan] = 0 ;
else if (pima->stepindx [chan] > 88)
pima->stepindx [chan] = 88 ;
pima->samples [k] = bytecode ;
} ;
/* Pack the 4 bit encoded samples. */
blockindx = 4 * pima->channels ;
indxstart = pima->channels ;
while (blockindx < pima->blocksize)
{ for (chan = 0 ; chan < pima->channels ; chan++)
{ indx = indxstart + chan ;
for (k = 0 ; k < 4 ; k++)
{ pima->block [blockindx] = pima->samples [indx] & 0x0F ;
indx += pima->channels ;
pima->block [blockindx] |= (pima->samples [indx] << 4) & 0xF0 ;
indx += pima->channels ;
blockindx ++ ;
} ;
} ;
indxstart += 8 * pima->channels ;
} ;
/* Write the block to disk. */
if ((k = psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ;
memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ;
pima->samplecount = 0 ;
pima->blockcount ++ ;
return 1 ;
} /* wav_w64_ima_encode_block */
static int
ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ if (pima->blockcount >= pima->blocks && pima->samplecount >= pima->samplesperblock)
{ memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ;
return total ;
} ;
if (pima->samplecount >= pima->samplesperblock)
pima->decode_block (psf, pima) ;
count = (pima->samplesperblock - pima->samplecount) * pima->channels ;
count = (len - indx > count) ? count : len - indx ;
memcpy (&(ptr [indx]), &(pima->samples [pima->samplecount * pima->channels]), count * sizeof (short)) ;
indx += count ;
pima->samplecount += count / pima->channels ;
total = indx ;
} ;
return total ;
} /* ima_read_block */
static sf_count_t
ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ IMA_ADPCM_PRIVATE *pima ;
int readcount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
while (len > 0)
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = ima_read_block (psf, pima, ptr, readcount) ;
total += count ;
len -= count ;
if (count != readcount)
break ;
} ;
return total ;
} /* ima_read_s */
static sf_count_t
ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ IMA_ADPCM_PRIVATE *pima ;
short *sptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = ima_read_block (psf, pima, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = ((int) sptr [k]) << 16 ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* ima_read_i */
static sf_count_t
ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ IMA_ADPCM_PRIVATE *pima ;
short *sptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = ima_read_block (psf, pima, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (float) (sptr [k]) ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* ima_read_f */
static sf_count_t
ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ IMA_ADPCM_PRIVATE *pima ;
short *sptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
double normfact ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = ima_read_block (psf, pima, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (double) (sptr [k]) ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* ima_read_d */
static sf_count_t
ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{ IMA_ADPCM_PRIVATE *pima ;
int newblock, newsample ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
if (psf->datalength < 0 || psf->dataoffset < 0)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
if (offset == 0)
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
pima->blockcount = 0 ;
pima->decode_block (psf, pima) ;
pima->samplecount = 0 ;
return 0 ;
} ;
if (offset < 0 || offset > pima->blocks * pima->samplesperblock)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
newblock = offset / pima->samplesperblock ;
newsample = offset % pima->samplesperblock ;
if (mode == SFM_READ)
{ psf_fseek (psf, psf->dataoffset + newblock * pima->blocksize, SEEK_SET) ;
pima->blockcount = newblock ;
pima->decode_block (psf, pima) ;
pima->samplecount = newsample ;
}
else
{ /* What to do about write??? */
psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
return newblock * pima->samplesperblock + newsample ;
} /* ima_seek */
/*==========================================================================================
** IMA ADPCM Write Functions.
*/
static int
ima_writer_init (SF_PRIVATE *psf, int blockalign)
{ IMA_ADPCM_PRIVATE *pima ;
int samplesperblock ;
unsigned int pimasize ;
if (psf->mode != SFM_WRITE)
return SFE_BAD_MODE_RW ;
samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ;
if ((pima = calloc (1, pimasize)) == NULL)
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pima ;
pima->channels = psf->sf.channels ;
pima->blocksize = blockalign ;
pima->samplesperblock = samplesperblock ;
pima->block = (unsigned char*) pima->data ;
pima->samples = (short*) (pima->data + blockalign) ;
pima->samplecount = 0 ;
switch (psf->sf.format & SF_FORMAT_TYPEMASK)
{ case SF_FORMAT_WAV :
case SF_FORMAT_W64 :
pima->encode_block = wav_w64_ima_encode_block ;
break ;
case SF_FORMAT_AIFF :
pima->encode_block = aiff_ima_encode_block ;
break ;
default :
psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
return SFE_INTERNAL ;
break ;
} ;
psf->write_short = ima_write_s ;
psf->write_int = ima_write_i ;
psf->write_float = ima_write_f ;
psf->write_double = ima_write_d ;
return 0 ;
} /* ima_writer_init */
/*==========================================================================================
*/
static int
ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ count = (pima->samplesperblock - pima->samplecount) * pima->channels ;
if (count > len - indx)
count = len - indx ;
memcpy (&(pima->samples [pima->samplecount * pima->channels]), &(ptr [total]), count * sizeof (short)) ;
indx += count ;
pima->samplecount += count / pima->channels ;
total = indx ;
if (pima->samplecount >= pima->samplesperblock)
pima->encode_block (psf, pima) ;
} ;
return total ;
} /* ima_write_block */
static sf_count_t
ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ IMA_ADPCM_PRIVATE *pima ;
int writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
while (len)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = ima_write_block (psf, pima, ptr, writecount) ;
total += count ;
len -= count ;
if (count != writecount)
break ;
} ;
return total ;
} /* ima_write_s */
static sf_count_t
ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ IMA_ADPCM_PRIVATE *pima ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = ptr [total + k] >> 16 ;
count = ima_write_block (psf, pima, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* ima_write_i */
static sf_count_t
ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ IMA_ADPCM_PRIVATE *pima ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = lrintf (normfact * ptr [total + k]) ;
count = ima_write_block (psf, pima, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* ima_write_f */
static sf_count_t
ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ IMA_ADPCM_PRIVATE *pima ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
double normfact ;
if (! psf->fdata)
return 0 ;
pima = (IMA_ADPCM_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = lrint (normfact * ptr [total + k]) ;
count = ima_write_block (psf, pima, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* ima_write_d */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 75a54b82-ad18-4758-9933-64e00a7f24e0
*/

View File

@@ -0,0 +1,306 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfendian.h"
#include <stdlib.h>
#include "sndfile.h"
#include "common.h"
#define INTERLEAVE_CHANNELS 6
typedef struct
{ double buffer [SF_BUFFER_LEN / sizeof (double)] ;
sf_count_t channel_len ;
sf_count_t (*read_short) (SF_PRIVATE*, short *ptr, sf_count_t len) ;
sf_count_t (*read_int) (SF_PRIVATE*, int *ptr, sf_count_t len) ;
sf_count_t (*read_float) (SF_PRIVATE*, float *ptr, sf_count_t len) ;
sf_count_t (*read_double) (SF_PRIVATE*, double *ptr, sf_count_t len) ;
} INTERLEAVE_DATA ;
static sf_count_t interleave_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t interleave_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t interleave_read_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t interleave_seek (SF_PRIVATE*, int mode, sf_count_t samples_from_start) ;
int
interleave_init (SF_PRIVATE *psf)
{ INTERLEAVE_DATA *pdata ;
if (psf->mode != SFM_READ)
return SFE_INTERLEAVE_MODE ;
if (psf->interleave)
{ psf_log_printf (psf, "*** Weird, already have interleave.\n") ;
return 666 ;
} ;
/* Free this in sf_close() function. */
if (! (pdata = malloc (sizeof (INTERLEAVE_DATA))))
return SFE_MALLOC_FAILED ;
puts ("interleave_init") ;
psf->interleave = pdata ;
/* Save the existing methods. */
pdata->read_short = psf->read_short ;
pdata->read_int = psf->read_int ;
pdata->read_float = psf->read_float ;
pdata->read_double = psf->read_double ;
pdata->channel_len = psf->sf.frames * psf->bytewidth ;
/* Insert our new methods. */
psf->read_short = interleave_read_short ;
psf->read_int = interleave_read_int ;
psf->read_float = interleave_read_float ;
psf->read_double = interleave_read_double ;
psf->seek = interleave_seek ;
return 0 ;
} /* pcm_interleave_init */
/*------------------------------------------------------------------------------
*/
static sf_count_t
interleave_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ INTERLEAVE_DATA *pdata ;
sf_count_t offset, templen ;
int chan, count, k ;
short *inptr, *outptr ;
if (! (pdata = psf->interleave))
return 0 ;
inptr = (short*) pdata->buffer ;
for (chan = 0 ; chan < psf->sf.channels ; chan++)
{ outptr = ptr + chan ;
offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
if (psf_fseek (psf, offset, SEEK_SET) != offset)
{ psf->error = SFE_INTERLEAVE_SEEK ;
return 0 ;
} ;
templen = len / psf->sf.channels ;
while (templen > 0)
{ if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short))
count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short) ;
else
count = (int) templen ;
if (pdata->read_short (psf, inptr, count) != count)
{ psf->error = SFE_INTERLEAVE_READ ;
return 0 ;
} ;
for (k = 0 ; k < count ; k++)
{ *outptr = inptr [k] ;
outptr += psf->sf.channels ;
} ;
templen -= count ;
} ;
} ;
return len ;
} /* interleave_read_short */
static sf_count_t
interleave_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ INTERLEAVE_DATA *pdata ;
sf_count_t offset, templen ;
int chan, count, k ;
int *inptr, *outptr ;
if (! (pdata = psf->interleave))
return 0 ;
inptr = (int*) pdata->buffer ;
for (chan = 0 ; chan < psf->sf.channels ; chan++)
{ outptr = ptr + chan ;
offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
if (psf_fseek (psf, offset, SEEK_SET) != offset)
{ psf->error = SFE_INTERLEAVE_SEEK ;
return 0 ;
} ;
templen = len / psf->sf.channels ;
while (templen > 0)
{ if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int))
count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int) ;
else
count = (int) templen ;
if (pdata->read_int (psf, inptr, count) != count)
{ psf->error = SFE_INTERLEAVE_READ ;
return 0 ;
} ;
for (k = 0 ; k < count ; k++)
{ *outptr = inptr [k] ;
outptr += psf->sf.channels ;
} ;
templen -= count ;
} ;
} ;
return len ;
} /* interleave_read_int */
static sf_count_t
interleave_read_float (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ INTERLEAVE_DATA *pdata ;
sf_count_t offset, templen ;
int chan, count, k ;
float *inptr, *outptr ;
if (! (pdata = psf->interleave))
return 0 ;
inptr = (float*) pdata->buffer ;
for (chan = 0 ; chan < psf->sf.channels ; chan++)
{ outptr = ptr + chan ;
offset = psf->dataoffset + pdata->channel_len * chan + psf->read_current * psf->bytewidth ;
/*-printf ("chan : %d read_current : %6lld offset : %6lld\n", chan, psf->read_current, offset) ;-*/
if (psf_fseek (psf, offset, SEEK_SET) != offset)
{ psf->error = SFE_INTERLEAVE_SEEK ;
/*-puts ("interleave_seek error") ; exit (1) ;-*/
return 0 ;
} ;
templen = len / psf->sf.channels ;
while (templen > 0)
{ if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float))
count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float) ;
else
count = (int) templen ;
if (pdata->read_float (psf, inptr, count) != count)
{ psf->error = SFE_INTERLEAVE_READ ;
/*-puts ("interleave_read error") ; exit (1) ;-*/
return 0 ;
} ;
for (k = 0 ; k < count ; k++)
{ *outptr = inptr [k] ;
outptr += psf->sf.channels ;
} ;
templen -= count ;
} ;
} ;
return len ;
} /* interleave_read_float */
static sf_count_t
interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ INTERLEAVE_DATA *pdata ;
sf_count_t offset, templen ;
int chan, count, k ;
double *inptr, *outptr ;
if (! (pdata = psf->interleave))
return 0 ;
inptr = (double*) pdata->buffer ;
for (chan = 0 ; chan < psf->sf.channels ; chan++)
{ outptr = ptr + chan ;
offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
if (psf_fseek (psf, offset, SEEK_SET) != offset)
{ psf->error = SFE_INTERLEAVE_SEEK ;
return 0 ;
} ;
templen = len / psf->sf.channels ;
while (templen > 0)
{ if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double))
count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double) ;
else
count = (int) templen ;
if (pdata->read_double (psf, inptr, count) != count)
{ psf->error = SFE_INTERLEAVE_READ ;
return 0 ;
} ;
for (k = 0 ; k < count ; k++)
{ *outptr = inptr [k] ;
outptr += psf->sf.channels ;
} ;
templen -= count ;
} ;
} ;
return len ;
} /* interleave_read_double */
/*------------------------------------------------------------------------------
*/
static sf_count_t
interleave_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start)
{ psf = psf ; mode = mode ;
/*
** Do nothing here. This is a place holder to prevent the default
** seek function from being called.
*/
return samples_from_start ;
} /* interleave_seek */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 82314e13-0225-4408-a2f2-e6dab3f38904
*/

331
libs/libsndfile/src/ircam.c Normal file
View File

@@ -0,0 +1,331 @@
/*
** Copyright (C) 2001-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
/* The IRCAM magic number is weird in that one byte in the number can have
** values of 0x1, 0x2, 0x03 or 0x04. Hence the need for a marker and a mask.
*/
#define IRCAM_BE_MASK (MAKE_MARKER (0xFF, 0xFF, 0x00, 0xFF))
#define IRCAM_BE_MARKER (MAKE_MARKER (0x64, 0xA3, 0x00, 0x00))
#define IRCAM_LE_MASK (MAKE_MARKER (0xFF, 0x00, 0xFF, 0xFF))
#define IRCAM_LE_MARKER (MAKE_MARKER (0x00, 0x00, 0xA3, 0x64))
#define IRCAM_02B_MARKER (MAKE_MARKER (0x64, 0xA3, 0x02, 0x00))
#define IRCAM_03L_MARKER (MAKE_MARKER (0x64, 0xA3, 0x03, 0x00))
#define IRCAM_DATA_OFFSET (1024)
/*------------------------------------------------------------------------------
** Typedefs.
*/
enum
{ IRCAM_PCM_16 = 0x00002,
IRCAM_FLOAT = 0x00004,
IRCAM_ALAW = 0x10001,
IRCAM_ULAW = 0x20001,
IRCAM_PCM_32 = 0x40004
} ;
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int ircam_close (SF_PRIVATE *psf) ;
static int ircam_write_header (SF_PRIVATE *psf, int calc_length) ;
static int ircam_read_header (SF_PRIVATE *psf) ;
static int get_encoding (int subformat) ;
static const char* get_encoding_str (int encoding) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
ircam_open (SF_PRIVATE *psf)
{ int subformat ;
int error = SFE_NO_ERROR ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = ircam_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_IRCAM)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)
psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
psf->dataoffset = IRCAM_DATA_OFFSET ;
if ((error = ircam_write_header (psf, SF_FALSE)))
return error ;
psf->write_header = ircam_write_header ;
} ;
psf->container_close = ircam_close ;
switch (subformat)
{ case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */
error = ulaw_init (psf) ;
break ;
case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */
error = alaw_init (psf) ;
break ;
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */
error = pcm_init (psf) ;
break ;
case SF_FORMAT_FLOAT : /* 32-bit linear PCM. */
error = float32_init (psf) ;
break ;
default : break ;
} ;
return error ;
} /* ircam_open */
/*------------------------------------------------------------------------------
*/
static int
ircam_read_header (SF_PRIVATE *psf)
{ unsigned int marker, encoding ;
float samplerate ;
int error = SFE_NO_ERROR ;
psf_binheader_readf (psf, "epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ;
if (((marker & IRCAM_BE_MASK) != IRCAM_BE_MARKER) && ((marker & IRCAM_LE_MASK) != IRCAM_LE_MARKER))
{ psf_log_printf (psf, "marker: 0x%X\n", marker) ;
return SFE_IRCAM_NO_MARKER ;
} ;
psf->endian = SF_ENDIAN_LITTLE ;
if (psf->sf.channels > 256)
{ psf_binheader_readf (psf, "Epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ;
/* Sanity checking for endian-ness detection. */
if (psf->sf.channels > 256)
{ psf_log_printf (psf, "marker: 0x%X\n", marker) ;
return SFE_IRCAM_BAD_CHANNELS ;
} ;
psf->endian = SF_ENDIAN_BIG ;
} ;
psf_log_printf (psf, "marker: 0x%X\n", marker) ;
psf->sf.samplerate = (int) samplerate ;
psf_log_printf (psf, " Sample Rate : %d\n"
" Channels : %d\n"
" Encoding : %X => %s\n", psf->sf.samplerate, psf->sf.channels, encoding, get_encoding_str (encoding)) ;
switch (encoding)
{ case IRCAM_PCM_16 :
psf->bytewidth = 2 ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_16 ;
break ;
case IRCAM_PCM_32 :
psf->bytewidth = 4 ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_32 ;
break ;
case IRCAM_FLOAT :
psf->bytewidth = 4 ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_FLOAT ;
break ;
case IRCAM_ALAW :
psf->bytewidth = 1 ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ALAW ;
break ;
case IRCAM_ULAW :
psf->bytewidth = 1 ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ULAW ;
break ;
default :
error = SFE_IRCAM_UNKNOWN_FORMAT ;
break ;
} ;
if (psf->endian == SF_ENDIAN_BIG)
psf->sf.format |= SF_ENDIAN_BIG ;
else
psf->sf.format |= SF_ENDIAN_LITTLE ;
if (error)
return error ;
psf->dataoffset = IRCAM_DATA_OFFSET ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->sf.frames == 0 && psf->blockwidth)
psf->sf.frames = psf->datalength / psf->blockwidth ;
psf_log_printf (psf, " Samples : %d\n", psf->sf.frames) ;
psf_binheader_readf (psf, "p", IRCAM_DATA_OFFSET) ;
return 0 ;
} /* ircam_read_header */
static int
ircam_close (SF_PRIVATE *psf)
{
psf_log_printf (psf, "close\n") ;
return 0 ;
} /* ircam_close */
static int
ircam_write_header (SF_PRIVATE *psf, int calc_length)
{ int encoding ;
float samplerate ;
sf_count_t current ;
if (psf->pipeoffset > 0)
return 0 ;
current = psf_ftell (psf) ;
calc_length = calc_length ;
/* This also sets psf->endian. */
encoding = get_encoding (psf->sf.format & SF_FORMAT_SUBMASK) ;
if (encoding == 0)
return SFE_BAD_OPEN_FORMAT ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
if (psf->is_pipe == SF_FALSE)
psf_fseek (psf, 0, SEEK_SET) ;
samplerate = psf->sf.samplerate ;
switch (psf->endian)
{ case SF_ENDIAN_BIG :
psf_binheader_writef (psf, "Emf", IRCAM_02B_MARKER, samplerate) ;
psf_binheader_writef (psf, "E44", psf->sf.channels, encoding) ;
break ;
case SF_ENDIAN_LITTLE :
psf_binheader_writef (psf, "emf", IRCAM_03L_MARKER, samplerate) ;
psf_binheader_writef (psf, "e44", psf->sf.channels, encoding) ;
break ;
default : return SFE_BAD_OPEN_FORMAT ;
} ;
psf_binheader_writef (psf, "z", (size_t) (IRCAM_DATA_OFFSET - psf->headindex)) ;
/* Header construction complete so write it out. */
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* ircam_write_header */
static int
get_encoding (int subformat)
{ switch (subformat)
{ case SF_FORMAT_PCM_16 : return IRCAM_PCM_16 ;
case SF_FORMAT_PCM_32 : return IRCAM_PCM_32 ;
case SF_FORMAT_FLOAT : return IRCAM_FLOAT ;
case SF_FORMAT_ULAW : return IRCAM_ULAW ;
case SF_FORMAT_ALAW : return IRCAM_ALAW ;
default : break ;
} ;
return 0 ;
} /* get_encoding */
static const char*
get_encoding_str (int encoding)
{ switch (encoding)
{ case IRCAM_PCM_16 : return "16 bit PCM" ;
case IRCAM_FLOAT : return "32 bit float" ;
case IRCAM_ALAW : return "A law" ;
case IRCAM_ULAW : return "u law" ;
case IRCAM_PCM_32 : return "32 bit PCM" ;
} ;
return "Unknown encoding" ;
} /* get_encoding_str */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f2714ab8-f286-4c94-9740-edaf673a1c71
*/

View File

@@ -0,0 +1,39 @@
; Auto-generated by create_symbols_file.py
LIBRARY libsndfile-1.dll
EXPORTS
sf_command @1
sf_open @2
sf_close @3
sf_seek @4
sf_error @7
sf_perror @8
sf_error_str @9
sf_error_number @10
sf_format_check @11
sf_read_raw @16
sf_readf_short @17
sf_readf_int @18
sf_readf_float @19
sf_readf_double @20
sf_read_short @21
sf_read_int @22
sf_read_float @23
sf_read_double @24
sf_write_raw @32
sf_writef_short @33
sf_writef_int @34
sf_writef_float @35
sf_writef_double @36
sf_write_short @37
sf_write_int @38
sf_write_float @39
sf_write_double @40
sf_strerror @50
sf_get_string @60
sf_set_string @61
sf_open_fd @70
sf_open_virtual @80
sf_write_sync @90

View File

@@ -0,0 +1,58 @@
/*
** Copyright (C) 2003-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#if (OS_IS_MACOSX == 1)
#include <CoreServices.h>
int
macbinary3_open (SF_PRIVATE *psf)
{
if (psf)
return 0 ;
return 0 ;
} /* macbinary3_open */
#else
int
macbinary3_open (SF_PRIVATE *psf)
{
psf = psf ;
return 0 ;
} /* macbinary3_open */
#endif /* OS_IS_MACOSX */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: c397a7d7-1a31-4349-9684-bd29ef06211e
*/

View File

@@ -0,0 +1,63 @@
/*
** Copyright (C) 2003-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ')
int
macos_guess_file_type (SF_PRIVATE *psf, const char *filename)
{ static char rsrc_name [1024] ;
struct stat statbuf ;
int format ;
psf = psf ;
snprintf (rsrc_name, sizeof (rsrc_name), "%s/rsrc", filename) ;
/* If there is no resource fork, just return. */
if (stat (rsrc_name, &statbuf) != 0)
{ psf_log_printf (psf, "No resource fork.\n") ;
return 0 ;
} ;
if (statbuf.st_size == 0)
{ psf_log_printf (psf, "Have zero size resource fork.\n") ;
return 0 ;
} ;
format = 0 ;
return format ;
} /* macos_guess_file_type */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 5fbf66d7-9547-442a-9c73-92fd164f3a95
*/

394
libs/libsndfile/src/mat4.c Normal file
View File

@@ -0,0 +1,394 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#include "float_cast.h"
/*------------------------------------------------------------------------------
** Information on how to decode and encode this file was obtained in a PDF
** file which I found on http://www.wotsit.org/.
** Also did a lot of testing with GNU Octave but do not have access to
** Matlab (tm) and so could not test it there.
*/
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define MAT4_BE_DOUBLE (MAKE_MARKER (0, 0, 0x03, 0xE8))
#define MAT4_LE_DOUBLE (MAKE_MARKER (0, 0, 0, 0))
#define MAT4_BE_FLOAT (MAKE_MARKER (0, 0, 0x03, 0xF2))
#define MAT4_LE_FLOAT (MAKE_MARKER (0x0A, 0, 0, 0))
#define MAT4_BE_PCM_32 (MAKE_MARKER (0, 0, 0x03, 0xFC))
#define MAT4_LE_PCM_32 (MAKE_MARKER (0x14, 0, 0, 0))
#define MAT4_BE_PCM_16 (MAKE_MARKER (0, 0, 0x04, 0x06))
#define MAT4_LE_PCM_16 (MAKE_MARKER (0x1E, 0, 0, 0))
/* Can't see any reason to ever implement this. */
#define MAT4_BE_PCM_U8 (MAKE_MARKER (0, 0, 0x04, 0x1A))
#define MAT4_LE_PCM_U8 (MAKE_MARKER (0x32, 0, 0, 0))
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int mat4_close (SF_PRIVATE *psf) ;
static int mat4_format_to_encoding (int format, int endian) ;
static int mat4_write_header (SF_PRIVATE *psf, int calc_length) ;
static int mat4_read_header (SF_PRIVATE *psf) ;
static const char * mat4_marker_to_str (int marker) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
mat4_open (SF_PRIVATE *psf)
{ int subformat, error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = mat4_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_MAT4)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0))
psf->endian = SF_ENDIAN_LITTLE ;
else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0))
psf->endian = SF_ENDIAN_BIG ;
if ((error = mat4_write_header (psf, SF_FALSE)))
return error ;
psf->write_header = mat4_write_header ;
} ;
psf->container_close = mat4_close ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
switch (subformat)
{ case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_32 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_FLOAT :
error = float32_init (psf) ;
break ;
case SF_FORMAT_DOUBLE :
error = double64_init (psf) ;
break ;
default : break ;
} ;
if (error)
return error ;
return error ;
} /* mat4_open */
/*------------------------------------------------------------------------------
*/
static int
mat4_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
mat4_write_header (psf, SF_TRUE) ;
return 0 ;
} /* mat4_close */
/*------------------------------------------------------------------------------
*/
static int
mat4_write_header (SF_PRIVATE *psf, int calc_length)
{ sf_count_t current ;
int encoding ;
double samplerate ;
current = psf_ftell (psf) ;
if (calc_length)
{ psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->dataend)
psf->datalength -= psf->filelength - psf->dataend ;
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
} ;
encoding = mat4_format_to_encoding (psf->sf.format & SF_FORMAT_SUBMASK, psf->endian) ;
if (encoding == -1)
return SFE_BAD_OPEN_FORMAT ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
psf_fseek (psf, 0, SEEK_SET) ;
/* Need sample rate as a double for writing to the header. */
samplerate = psf->sf.samplerate ;
if (psf->endian == SF_ENDIAN_BIG)
{ psf_binheader_writef (psf, "Em444", MAT4_BE_DOUBLE, 1, 1, 0) ;
psf_binheader_writef (psf, "E4bd", 11, "samplerate", 11, samplerate) ;
psf_binheader_writef (psf, "tEm484", encoding, psf->sf.channels, psf->sf.frames, 0) ;
psf_binheader_writef (psf, "E4b", 9, "wavedata", 9) ;
}
else if (psf->endian == SF_ENDIAN_LITTLE)
{ psf_binheader_writef (psf, "em444", MAT4_LE_DOUBLE, 1, 1, 0) ;
psf_binheader_writef (psf, "e4bd", 11, "samplerate", 11, samplerate) ;
psf_binheader_writef (psf, "tem484", encoding, psf->sf.channels, psf->sf.frames, 0) ;
psf_binheader_writef (psf, "e4b", 9, "wavedata", 9) ;
}
else
return SFE_BAD_OPEN_FORMAT ;
/* Header construction complete so write it out. */
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* mat4_write_header */
static int
mat4_read_header (SF_PRIVATE *psf)
{ int marker, namesize, rows, cols, imag ;
double value ;
const char *marker_str ;
char name [64] ;
psf_binheader_readf (psf, "pm", 0, &marker) ;
/* MAT4 file must start with a double for the samplerate. */
if (marker == MAT4_BE_DOUBLE)
{ psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ;
marker_str = "big endian double" ;
}
else if (marker == MAT4_LE_DOUBLE)
{ psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ;
marker_str = "little endian double" ;
}
else
return SFE_UNIMPLEMENTED ;
psf_log_printf (psf, "GNU Octave 2.0 / MATLAB v4.2 format\nMarker : %s\n", marker_str) ;
psf_binheader_readf (psf, "444", &rows, &cols, &imag) ;
psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ;
psf_binheader_readf (psf, "4", &namesize) ;
if (namesize >= SIGNED_SIZEOF (name))
return SFE_MAT4_BAD_NAME ;
psf_binheader_readf (psf, "b", name, namesize) ;
name [namesize] = 0 ;
psf_log_printf (psf, " Name : %s\n", name) ;
psf_binheader_readf (psf, "d", &value) ;
LSF_SNPRINTF (psf->u.cbuf, sizeof (psf->u.cbuf), " Value : %f\n", value) ;
psf_log_printf (psf, psf->u.cbuf) ;
if ((rows != 1) || (cols != 1))
return SFE_MAT4_NO_SAMPLERATE ;
psf->sf.samplerate = lrint (value) ;
/* Now write out the audio data. */
psf_binheader_readf (psf, "m", &marker) ;
psf_log_printf (psf, "Marker : %s\n", mat4_marker_to_str (marker)) ;
psf_binheader_readf (psf, "444", &rows, &cols, &imag) ;
psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ;
psf_binheader_readf (psf, "4", &namesize) ;
if (namesize >= SIGNED_SIZEOF (name))
return SFE_MAT4_BAD_NAME ;
psf_binheader_readf (psf, "b", name, namesize) ;
name [namesize] = 0 ;
psf_log_printf (psf, " Name : %s\n", name) ;
psf->dataoffset = psf_ftell (psf) ;
if (rows == 0 && cols == 0)
{ psf_log_printf (psf, "*** Error : zero channel count.\n") ;
return SFE_MAT4_ZERO_CHANNELS ;
} ;
psf->sf.channels = rows ;
psf->sf.frames = cols ;
psf->sf.format = psf->endian | SF_FORMAT_MAT4 ;
switch (marker)
{ case MAT4_BE_DOUBLE :
case MAT4_LE_DOUBLE :
psf->sf.format |= SF_FORMAT_DOUBLE ;
psf->bytewidth = 8 ;
break ;
case MAT4_BE_FLOAT :
case MAT4_LE_FLOAT :
psf->sf.format |= SF_FORMAT_FLOAT ;
psf->bytewidth = 4 ;
break ;
case MAT4_BE_PCM_32 :
case MAT4_LE_PCM_32 :
psf->sf.format |= SF_FORMAT_PCM_32 ;
psf->bytewidth = 4 ;
break ;
case MAT4_BE_PCM_16 :
case MAT4_LE_PCM_16 :
psf->sf.format |= SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
break ;
default :
psf_log_printf (psf, "*** Error : Bad marker %08X\n", marker) ;
return SFE_UNIMPLEMENTED ;
} ;
if ((psf->filelength - psf->dataoffset) < psf->sf.channels * psf->sf.frames * psf->bytewidth)
{ psf_log_printf (psf, "*** File seems to be truncated. %D <--> %D\n",
psf->filelength - psf->dataoffset, psf->sf.channels * psf->sf.frames * psf->bytewidth) ;
}
else if ((psf->filelength - psf->dataoffset) > psf->sf.channels * psf->sf.frames * psf->bytewidth)
psf->dataend = psf->dataoffset + rows * cols * psf->bytewidth ;
psf->datalength = psf->filelength - psf->dataoffset - psf->dataend ;
psf->sf.sections = 1 ;
return 0 ;
} /* mat4_read_header */
static int
mat4_format_to_encoding (int format, int endian)
{
switch (format | endian)
{ case (SF_FORMAT_PCM_16 | SF_ENDIAN_BIG) :
return MAT4_BE_PCM_16 ;
case (SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE) :
return MAT4_LE_PCM_16 ;
case (SF_FORMAT_PCM_32 | SF_ENDIAN_BIG) :
return MAT4_BE_PCM_32 ;
case (SF_FORMAT_PCM_32 | SF_ENDIAN_LITTLE) :
return MAT4_LE_PCM_32 ;
case (SF_FORMAT_FLOAT | SF_ENDIAN_BIG) :
return MAT4_BE_FLOAT ;
case (SF_FORMAT_FLOAT | SF_ENDIAN_LITTLE) :
return MAT4_LE_FLOAT ;
case (SF_FORMAT_DOUBLE | SF_ENDIAN_BIG) :
return MAT4_BE_DOUBLE ;
case (SF_FORMAT_DOUBLE | SF_ENDIAN_LITTLE) :
return MAT4_LE_DOUBLE ;
default : break ;
} ;
return -1 ;
} /* mat4_format_to_encoding */
static const char *
mat4_marker_to_str (int marker)
{ static char str [32] ;
switch (marker)
{
case MAT4_BE_PCM_16 : return "big endian 16 bit PCM" ;
case MAT4_LE_PCM_16 : return "little endian 16 bit PCM" ;
case MAT4_BE_PCM_32 : return "big endian 32 bit PCM" ;
case MAT4_LE_PCM_32 : return "little endian 32 bit PCM" ;
case MAT4_BE_FLOAT : return "big endian float" ;
case MAT4_LE_FLOAT : return "big endian float" ;
case MAT4_BE_DOUBLE : return "big endian double" ;
case MAT4_LE_DOUBLE : return "little endian double" ;
} ;
/* This is a little unsafe but is really only for debugging. */
str [sizeof (str) - 1] = 0 ;
LSF_SNPRINTF (str, sizeof (str) - 1, "%08X", marker) ;
return str ;
} /* mat4_marker_to_str */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f7e5f5d6-fc39-452e-bc4a-59627116ff59
*/

507
libs/libsndfile/src/mat5.c Normal file
View File

@@ -0,0 +1,507 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#include "float_cast.h"
/*------------------------------------------------------------------------------
** Information on how to decode and encode this file was obtained in a PDF
** file which I found on http://www.wotsit.org/.
** Also did a lot of testing with GNU Octave but do not have access to
** Matlab (tm) and so could not test it there.
*/
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define MATL_MARKER (MAKE_MARKER ('M', 'A', 'T', 'L'))
#define IM_MARKER (('I' << 8) + 'M')
#define MI_MARKER (('M' << 8) + 'I')
/*------------------------------------------------------------------------------
** Enums and typedefs.
*/
enum
{ MAT5_TYPE_SCHAR = 0x1,
MAT5_TYPE_UCHAR = 0x2,
MAT5_TYPE_INT16 = 0x3,
MAT5_TYPE_UINT16 = 0x4,
MAT5_TYPE_INT32 = 0x5,
MAT5_TYPE_UINT32 = 0x6,
MAT5_TYPE_FLOAT = 0x7,
MAT5_TYPE_DOUBLE = 0x9,
MAT5_TYPE_ARRAY = 0xE,
MAT5_TYPE_COMP_USHORT = 0x00020004,
MAT5_TYPE_COMP_UINT = 0x00040006
} ;
typedef struct
{ sf_count_t size ;
int rows, cols ;
char name [32] ;
} MAT5_MATRIX ;
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int mat5_close (SF_PRIVATE *psf) ;
static int mat5_write_header (SF_PRIVATE *psf, int calc_length) ;
static int mat5_read_header (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
mat5_open (SF_PRIVATE *psf)
{ int subformat, error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = mat5_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_MAT5)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0))
psf->endian = SF_ENDIAN_LITTLE ;
else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0))
psf->endian = SF_ENDIAN_BIG ;
if ((error = mat5_write_header (psf, SF_FALSE)))
return error ;
psf->write_header = mat5_write_header ;
} ;
psf->container_close = mat5_close ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
switch (subformat)
{ case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_32 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_FLOAT :
error = float32_init (psf) ;
break ;
case SF_FORMAT_DOUBLE :
error = double64_init (psf) ;
break ;
default : break ;
} ;
return error ;
} /* mat5_open */
/*------------------------------------------------------------------------------
*/
static int
mat5_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
mat5_write_header (psf, SF_TRUE) ;
return 0 ;
} /* mat5_close */
/*------------------------------------------------------------------------------
*/
static int
mat5_write_header (SF_PRIVATE *psf, int calc_length)
{ static const char *filename = "MATLAB 5.0 MAT-file, written by " PACKAGE "-" VERSION ", " ;
static const char *sr_name = "samplerate\0\0\0\0\0\0\0\0\0\0\0" ;
static const char *wd_name = "wavedata\0" ;
sf_count_t current, datasize ;
int encoding ;
current = psf_ftell (psf) ;
if (calc_length)
{ psf_fseek (psf, 0, SEEK_END) ;
psf->filelength = psf_ftell (psf) ;
psf_fseek (psf, 0, SEEK_SET) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->dataend)
psf->datalength -= psf->filelength - psf->dataend ;
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
} ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_U8 :
encoding = MAT5_TYPE_UCHAR ;
break ;
case SF_FORMAT_PCM_16 :
encoding = MAT5_TYPE_INT16 ;
break ;
case SF_FORMAT_PCM_32 :
encoding = MAT5_TYPE_INT32 ;
break ;
case SF_FORMAT_FLOAT :
encoding = MAT5_TYPE_FLOAT ;
break ;
case SF_FORMAT_DOUBLE :
encoding = MAT5_TYPE_DOUBLE ;
break ;
default :
return SFE_BAD_OPEN_FORMAT ;
} ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
psf_fseek (psf, 0, SEEK_SET) ;
psf_get_date_str (psf->u.cbuf, sizeof (psf->u.scbuf)) ;
psf_binheader_writef (psf, "bb", filename, strlen (filename), psf->u.cbuf, strlen (psf->u.cbuf) + 1) ;
memset (psf->u.scbuf, ' ', 124 - psf->headindex) ;
psf_binheader_writef (psf, "b", psf->u.scbuf, 124 - psf->headindex) ;
psf->rwf_endian = psf->endian ;
if (psf->rwf_endian == SF_ENDIAN_BIG)
psf_binheader_writef (psf, "2b", 0x0100, "MI", 2) ;
else
psf_binheader_writef (psf, "2b", 0x0100, "IM", 2) ;
psf_binheader_writef (psf, "444444", MAT5_TYPE_ARRAY, 64, MAT5_TYPE_UINT32, 8, 6, 0) ;
psf_binheader_writef (psf, "4444", MAT5_TYPE_INT32, 8, 1, 1) ;
psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (sr_name), sr_name, 16) ;
if (psf->sf.samplerate > 0xFFFF)
psf_binheader_writef (psf, "44", MAT5_TYPE_COMP_UINT, psf->sf.samplerate) ;
else
{ unsigned short samplerate = psf->sf.samplerate ;
psf_binheader_writef (psf, "422", MAT5_TYPE_COMP_USHORT, samplerate, 0) ;
} ;
datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ;
psf_binheader_writef (psf, "t484444", MAT5_TYPE_ARRAY, datasize + 64, MAT5_TYPE_UINT32, 8, 6, 0) ;
psf_binheader_writef (psf, "t4448", MAT5_TYPE_INT32, 8, psf->sf.channels, psf->sf.frames) ;
psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (wd_name), wd_name, strlen (wd_name)) ;
datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ;
if (datasize > 0x7FFFFFFF)
datasize = 0x7FFFFFFF ;
psf_binheader_writef (psf, "t48", encoding, datasize) ;
/* Header construction complete so write it out. */
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* mat5_write_header */
static int
mat5_read_header (SF_PRIVATE *psf)
{ char name [32] ;
short version, endian ;
int type, size, flags1, flags2, rows, cols ;
psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, 124) ;
psf->u.scbuf [125] = 0 ;
if (strlen (psf->u.cbuf) >= 124)
return SFE_UNIMPLEMENTED ;
if (strstr (psf->u.cbuf, "MATLAB 5.0 MAT-file") == psf->u.cbuf)
psf_log_printf (psf, "%s\n", psf->u.scbuf) ;
psf_binheader_readf (psf, "E22", &version, &endian) ;
if (endian == MI_MARKER)
{ psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ;
if (CPU_IS_LITTLE_ENDIAN) version = ENDSWAP_SHORT (version) ;
}
else if (endian == IM_MARKER)
{ psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ;
if (CPU_IS_BIG_ENDIAN) version = ENDSWAP_SHORT (version) ;
}
else
return SFE_MAT5_BAD_ENDIAN ;
if ((CPU_IS_LITTLE_ENDIAN && endian == IM_MARKER) ||
(CPU_IS_BIG_ENDIAN && endian == MI_MARKER))
version = ENDSWAP_SHORT (version) ;
psf_log_printf (psf, "Version : 0x%04X\n", version) ;
psf_log_printf (psf, "Endian : 0x%04X => %s\n", endian,
(psf->endian == SF_ENDIAN_LITTLE) ? "Little" : "Big") ;
/*========================================================*/
psf_binheader_readf (psf, "44", &type, &size) ;
psf_log_printf (psf, "Block\n Type : %X Size : %d\n", type, size) ;
if (type != MAT5_TYPE_ARRAY)
return SFE_MAT5_NO_BLOCK ;
psf_binheader_readf (psf, "44", &type, &size) ;
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
if (type != MAT5_TYPE_UINT32)
return SFE_MAT5_NO_BLOCK ;
psf_binheader_readf (psf, "44", &flags1, &flags2) ;
psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ;
psf_binheader_readf (psf, "44", &type, &size) ;
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
if (type != MAT5_TYPE_INT32)
return SFE_MAT5_NO_BLOCK ;
psf_binheader_readf (psf, "44", &rows, &cols) ;
psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ;
if (rows != 1 || cols != 1)
return SFE_MAT5_SAMPLE_RATE ;
psf_binheader_readf (psf, "4", &type) ;
if (type == MAT5_TYPE_SCHAR)
{ psf_binheader_readf (psf, "4", &size) ;
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
if (size > SIGNED_SIZEOF (name) - 1)
{ psf_log_printf (psf, "Error : Bad name length.\n") ;
return SFE_MAT5_NO_BLOCK ;
} ;
psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ;
name [size] = 0 ;
}
else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR)
{ size = type >> 16 ;
if (size > 4)
{ psf_log_printf (psf, "Error : Bad name length.\n") ;
return SFE_MAT5_NO_BLOCK ;
} ;
psf_log_printf (psf, " Type : %X\n", type) ;
psf_binheader_readf (psf, "4", &name) ;
name [size] = 0 ;
}
else
return SFE_MAT5_NO_BLOCK ;
psf_log_printf (psf, " Name : %s\n", name) ;
/*-----------------------------------------*/
psf_binheader_readf (psf, "44", &type, &size) ;
switch (type)
{ case MAT5_TYPE_DOUBLE :
{ double samplerate ;
psf_binheader_readf (psf, "d", &samplerate) ;
LSF_SNPRINTF (name, sizeof (name), "%f\n", samplerate) ;
psf_log_printf (psf, " Val : %s\n", name) ;
psf->sf.samplerate = lrint (samplerate) ;
} ;
break ;
case MAT5_TYPE_COMP_USHORT :
{ unsigned short samplerate ;
psf_binheader_readf (psf, "j2j", -4, &samplerate, 2) ;
psf_log_printf (psf, " Val : %u\n", samplerate) ;
psf->sf.samplerate = samplerate ;
}
break ;
case MAT5_TYPE_COMP_UINT :
psf_log_printf (psf, " Val : %u\n", size) ;
psf->sf.samplerate = size ;
break ;
default :
psf_log_printf (psf, " Type : %X Size : %d ***\n", type, size) ;
return SFE_MAT5_SAMPLE_RATE ;
} ;
/*-----------------------------------------*/
psf_binheader_readf (psf, "44", &type, &size) ;
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
if (type != MAT5_TYPE_ARRAY)
return SFE_MAT5_NO_BLOCK ;
psf_binheader_readf (psf, "44", &type, &size) ;
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
if (type != MAT5_TYPE_UINT32)
return SFE_MAT5_NO_BLOCK ;
psf_binheader_readf (psf, "44", &flags1, &flags2) ;
psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ;
psf_binheader_readf (psf, "44", &type, &size) ;
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
if (type != MAT5_TYPE_INT32)
return SFE_MAT5_NO_BLOCK ;
psf_binheader_readf (psf, "44", &rows, &cols) ;
psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ;
psf_binheader_readf (psf, "4", &type) ;
if (type == MAT5_TYPE_SCHAR)
{ psf_binheader_readf (psf, "4", &size) ;
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
if (size > SIGNED_SIZEOF (name) - 1)
{ psf_log_printf (psf, "Error : Bad name length.\n") ;
return SFE_MAT5_NO_BLOCK ;
} ;
psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ;
name [size] = 0 ;
}
else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR)
{ size = type >> 16 ;
if (size > 4)
{ psf_log_printf (psf, "Error : Bad name length.\n") ;
return SFE_MAT5_NO_BLOCK ;
} ;
psf_log_printf (psf, " Type : %X\n", type) ;
psf_binheader_readf (psf, "4", &name) ;
name [size] = 0 ;
}
else
return SFE_MAT5_NO_BLOCK ;
psf_log_printf (psf, " Name : %s\n", name) ;
psf_binheader_readf (psf, "44", &type, &size) ;
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
/*++++++++++++++++++++++++++++++++++++++++++++++++++*/
if (rows == 0 && cols == 0)
{ psf_log_printf (psf, "*** Error : zero channel count.\n") ;
return SFE_MAT5_ZERO_CHANNELS ;
} ;
psf->sf.channels = rows ;
psf->sf.frames = cols ;
psf->sf.format = psf->endian | SF_FORMAT_MAT5 ;
switch (type)
{ case MAT5_TYPE_DOUBLE :
psf_log_printf (psf, "Data type : double\n") ;
psf->sf.format |= SF_FORMAT_DOUBLE ;
psf->bytewidth = 8 ;
break ;
case MAT5_TYPE_FLOAT :
psf_log_printf (psf, "Data type : float\n") ;
psf->sf.format |= SF_FORMAT_FLOAT ;
psf->bytewidth = 4 ;
break ;
case MAT5_TYPE_INT32 :
psf_log_printf (psf, "Data type : 32 bit PCM\n") ;
psf->sf.format |= SF_FORMAT_PCM_32 ;
psf->bytewidth = 4 ;
break ;
case MAT5_TYPE_INT16 :
psf_log_printf (psf, "Data type : 16 bit PCM\n") ;
psf->sf.format |= SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
break ;
case MAT5_TYPE_UCHAR :
psf_log_printf (psf, "Data type : unsigned 8 bit PCM\n") ;
psf->sf.format |= SF_FORMAT_PCM_U8 ;
psf->bytewidth = 1 ;
break ;
default :
psf_log_printf (psf, "*** Error : Bad marker %08X\n", type) ;
return SFE_UNIMPLEMENTED ;
} ;
psf->dataoffset = psf_ftell (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
return 0 ;
} /* mat5_read_header */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: dfdb6742-b2be-4be8-b390-d0c674e8bc8e
*/

View File

@@ -0,0 +1,834 @@
/*
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
#include "wav_w64.h"
/* These required here because we write the header in this file. */
#define RIFF_MARKER (MAKE_MARKER ('R', 'I', 'F', 'F'))
#define WAVE_MARKER (MAKE_MARKER ('W', 'A', 'V', 'E'))
#define fmt_MARKER (MAKE_MARKER ('f', 'm', 't', ' '))
#define fact_MARKER (MAKE_MARKER ('f', 'a', 'c', 't'))
#define data_MARKER (MAKE_MARKER ('d', 'a', 't', 'a'))
#define WAVE_FORMAT_MS_ADPCM 0x0002
typedef struct
{ int channels, blocksize, samplesperblock, blocks, dataremaining ;
int blockcount ;
sf_count_t samplecount ;
short *samples ;
unsigned char *block ;
#if HAVE_FLEXIBLE_ARRAY
short dummydata [] ; /* ISO C99 struct flexible array. */
#else
short dummydata [0] ; /* This is a hack an might not work. */
#endif
} MSADPCM_PRIVATE ;
/*============================================================================================
** MS ADPCM static data and functions.
*/
static int AdaptationTable [] =
{ 230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
} ;
/* TODO : The first 7 coef's are are always hardcode and must
appear in the actual WAVE file. They should be read in
in case a sound program added extras to the list. */
static int AdaptCoeff1 [MSADPCM_ADAPT_COEFF_COUNT] =
{ 256, 512, 0, 192, 240, 460, 392
} ;
static int AdaptCoeff2 [MSADPCM_ADAPT_COEFF_COUNT] =
{ 0, -256, 0, 64, 0, -208, -232
} ;
/*============================================================================================
** MS ADPCM Block Layout.
** ======================
** Block is usually 256, 512 or 1024 bytes depending on sample rate.
** For a mono file, the block is laid out as follows:
** byte purpose
** 0 block predictor [0..6]
** 1,2 initial idelta (positive)
** 3,4 sample 1
** 5,6 sample 0
** 7..n packed bytecodes
**
** For a stereo file, the block is laid out as follows:
** byte purpose
** 0 block predictor [0..6] for left channel
** 1 block predictor [0..6] for right channel
** 2,3 initial idelta (positive) for left channel
** 4,5 initial idelta (positive) for right channel
** 6,7 sample 1 for left channel
** 8,9 sample 1 for right channel
** 10,11 sample 0 for left channel
** 12,13 sample 0 for right channel
** 14..n packed bytecodes
*/
/*============================================================================================
** Static functions.
*/
static int msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) ;
static sf_count_t msadpcm_read_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len) ;
static int msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) ;
static sf_count_t msadpcm_write_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, const short *ptr, int len) ;
static sf_count_t msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static sf_count_t msadpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int msadpcm_close (SF_PRIVATE *psf) ;
static void choose_predictor (unsigned int channels, short *data, int *bpred, int *idelta) ;
/*============================================================================================
** MS ADPCM Read Functions.
*/
int
wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
{ MSADPCM_PRIVATE *pms ;
unsigned int pmssize ;
int count ;
if (psf->fdata != NULL)
{ psf_log_printf (psf, "*** psf->fdata is not NULL.\n") ;
return SFE_INTERNAL ;
} ;
if (psf->mode == SFM_WRITE)
samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
pmssize = sizeof (MSADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ;
if (! (psf->fdata = malloc (pmssize)))
return SFE_MALLOC_FAILED ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
memset (pms, 0, pmssize) ;
pms->samples = pms->dummydata ;
pms->block = (unsigned char*) (pms->dummydata + psf->sf.channels * samplesperblock) ;
pms->channels = psf->sf.channels ;
pms->blocksize = blockalign ;
pms->samplesperblock = samplesperblock ;
if (psf->mode == SFM_READ)
{ pms->dataremaining = psf->datalength ;
if (psf->datalength % pms->blocksize)
pms->blocks = psf->datalength / pms->blocksize + 1 ;
else
pms->blocks = psf->datalength / pms->blocksize ;
count = 2 * (pms->blocksize - 6 * pms->channels) / pms->channels ;
if (pms->samplesperblock != count)
psf_log_printf (psf, "*** Warning : samplesperblock shoud be %d.\n", count) ;
psf->sf.frames = (psf->datalength / pms->blocksize) * pms->samplesperblock ;
psf_log_printf (psf, " bpred idelta\n") ;
msadpcm_decode_block (psf, pms) ;
psf->read_short = msadpcm_read_s ;
psf->read_int = msadpcm_read_i ;
psf->read_float = msadpcm_read_f ;
psf->read_double = msadpcm_read_d ;
} ;
if (psf->mode == SFM_WRITE)
{ pms->samples = pms->dummydata ;
pms->samplecount = 0 ;
psf->write_short = msadpcm_write_s ;
psf->write_int = msadpcm_write_i ;
psf->write_float = msadpcm_write_f ;
psf->write_double = msadpcm_write_d ;
} ;
psf->codec_close = msadpcm_close ;
psf->seek = msadpcm_seek ;
return 0 ;
} /* wav_w64_msadpcm_init */
static int
msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
{ int chan, k, blockindx, sampleindx ;
short bytecode, bpred [2], chan_idelta [2] ;
int predict ;
int current ;
int idelta ;
pms->blockcount ++ ;
pms->samplecount = 0 ;
if (pms->blockcount > pms->blocks)
{ memset (pms->samples, 0, pms->samplesperblock * pms->channels) ;
return 1 ;
} ;
if ((k = psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pms->blocksize) ;
/* Read and check the block header. */
if (pms->channels == 1)
{ bpred [0] = pms->block [0] ;
if (bpred [0] >= 7)
psf_log_printf (psf, "MS ADPCM synchronisation error (%d).\n", bpred [0]) ;
chan_idelta [0] = pms->block [1] | (pms->block [2] << 8) ;
chan_idelta [1] = 0 ;
psf_log_printf (psf, "(%d) (%d)\n", bpred [0], chan_idelta [0]) ;
pms->samples [1] = pms->block [3] | (pms->block [4] << 8) ;
pms->samples [0] = pms->block [5] | (pms->block [6] << 8) ;
blockindx = 7 ;
}
else
{ bpred [0] = pms->block [0] ;
bpred [1] = pms->block [1] ;
if (bpred [0] >= 7 || bpred [1] >= 7)
psf_log_printf (psf, "MS ADPCM synchronisation error (%d %d).\n", bpred [0], bpred [1]) ;
chan_idelta [0] = pms->block [2] | (pms->block [3] << 8) ;
chan_idelta [1] = pms->block [4] | (pms->block [5] << 8) ;
psf_log_printf (psf, "(%d, %d) (%d, %d)\n", bpred [0], bpred [1], chan_idelta [0], chan_idelta [1]) ;
pms->samples [2] = pms->block [6] | (pms->block [7] << 8) ;
pms->samples [3] = pms->block [8] | (pms->block [9] << 8) ;
pms->samples [0] = pms->block [10] | (pms->block [11] << 8) ;
pms->samples [1] = pms->block [12] | (pms->block [13] << 8) ;
blockindx = 14 ;
} ;
/*--------------------------------------------------------
This was left over from a time when calculations were done
as ints rather than shorts. Keep this around as a reminder
in case I ever find a file which decodes incorrectly.
if (chan_idelta [0] & 0x8000)
chan_idelta [0] -= 0x10000 ;
if (chan_idelta [1] & 0x8000)
chan_idelta [1] -= 0x10000 ;
--------------------------------------------------------*/
/* Pull apart the packed 4 bit samples and store them in their
** correct sample positions.
*/
sampleindx = 2 * pms->channels ;
while (blockindx < pms->blocksize)
{ bytecode = pms->block [blockindx++] ;
pms->samples [sampleindx++] = (bytecode >> 4) & 0x0F ;
pms->samples [sampleindx++] = bytecode & 0x0F ;
} ;
/* Decode the encoded 4 bit samples. */
for (k = 2 * pms->channels ; k < (pms->samplesperblock * pms->channels) ; k ++)
{ chan = (pms->channels > 1) ? (k % 2) : 0 ;
bytecode = pms->samples [k] & 0xF ;
/* Compute next Adaptive Scale Factor (ASF) */
idelta = chan_idelta [chan] ;
chan_idelta [chan] = (AdaptationTable [bytecode] * idelta) >> 8 ; /* => / 256 => FIXED_POINT_ADAPTATION_BASE == 256 */
if (chan_idelta [chan] < 16)
chan_idelta [chan] = 16 ;
if (bytecode & 0x8)
bytecode -= 0x10 ;
predict = ((pms->samples [k - pms->channels] * AdaptCoeff1 [bpred [chan]])
+ (pms->samples [k - 2 * pms->channels] * AdaptCoeff2 [bpred [chan]])) >> 8 ; /* => / 256 => FIXED_POINT_COEFF_BASE == 256 */
current = (bytecode * idelta) + predict ;
if (current > 32767)
current = 32767 ;
else if (current < -32768)
current = -32768 ;
pms->samples [k] = current ;
} ;
return 1 ;
} /* msadpcm_decode_block */
static sf_count_t
msadpcm_read_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ if (pms->blockcount >= pms->blocks && pms->samplecount >= pms->samplesperblock)
{ memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ;
return total ;
} ;
if (pms->samplecount >= pms->samplesperblock)
msadpcm_decode_block (psf, pms) ;
count = (pms->samplesperblock - pms->samplecount) * pms->channels ;
count = (len - indx > count) ? count : len - indx ;
memcpy (&(ptr [indx]), &(pms->samples [pms->samplecount * pms->channels]), count * sizeof (short)) ;
indx += count ;
pms->samplecount += count / pms->channels ;
total = indx ;
} ;
return total ;
} /* msadpcm_read_block */
static sf_count_t
msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
int readcount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
while (len > 0)
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = msadpcm_read_block (psf, pms, ptr, readcount) ;
total += count ;
len -= count ;
if (count != readcount)
break ;
} ;
return total ;
} /* msadpcm_read_s */
static sf_count_t
msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = sptr [k] << 16 ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* msadpcm_read_i */
static sf_count_t
msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (float) (sptr [k]) ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* msadpcm_read_f */
static sf_count_t
msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * (double) (sptr [k]) ;
total += count ;
len -= readcount ;
if (count != readcount)
break ;
} ;
return total ;
} /* msadpcm_read_d */
static sf_count_t
msadpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{ MSADPCM_PRIVATE *pms ;
int newblock, newsample ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
if (psf->datalength < 0 || psf->dataoffset < 0)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
if (offset == 0)
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
pms->blockcount = 0 ;
msadpcm_decode_block (psf, pms) ;
pms->samplecount = 0 ;
return 0 ;
} ;
if (offset < 0 || offset > pms->blocks * pms->samplesperblock)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
newblock = offset / pms->samplesperblock ;
newsample = offset % pms->samplesperblock ;
if (mode == SFM_READ)
{ psf_fseek (psf, psf->dataoffset + newblock * pms->blocksize, SEEK_SET) ;
pms->blockcount = newblock ;
msadpcm_decode_block (psf, pms) ;
pms->samplecount = newsample ;
}
else
{ /* What to do about write??? */
psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
return newblock * pms->samplesperblock + newsample ;
} /* msadpcm_seek */
/*==========================================================================================
** MS ADPCM Write Functions.
*/
void
msadpcm_write_adapt_coeffs (SF_PRIVATE *psf)
{ int k ;
for (k = 0 ; k < MSADPCM_ADAPT_COEFF_COUNT ; k++)
psf_binheader_writef (psf, "22", AdaptCoeff1 [k], AdaptCoeff2 [k]) ;
} /* msadpcm_write_adapt_coeffs */
/*==========================================================================================
*/
static int
msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
{ unsigned int blockindx ;
unsigned char byte ;
int chan, k, predict, bpred [2], idelta [2], errordelta, newsamp ;
choose_predictor (pms->channels, pms->samples, bpred, idelta) ;
/* Write the block header. */
if (pms->channels == 1)
{ pms->block [0] = bpred [0] ;
pms->block [1] = idelta [0] & 0xFF ;
pms->block [2] = idelta [0] >> 8 ;
pms->block [3] = pms->samples [1] & 0xFF ;
pms->block [4] = pms->samples [1] >> 8 ;
pms->block [5] = pms->samples [0] & 0xFF ;
pms->block [6] = pms->samples [0] >> 8 ;
blockindx = 7 ;
byte = 0 ;
/* Encode the samples as 4 bit. */
for (k = 2 ; k < pms->samplesperblock ; k++)
{ predict = (pms->samples [k-1] * AdaptCoeff1 [bpred [0]] + pms->samples [k-2] * AdaptCoeff2 [bpred [0]]) >> 8 ;
errordelta = (pms->samples [k] - predict) / idelta [0] ;
if (errordelta < -8)
errordelta = -8 ;
else if (errordelta > 7)
errordelta = 7 ;
newsamp = predict + (idelta [0] * errordelta) ;
if (newsamp > 32767)
newsamp = 32767 ;
else if (newsamp < -32768)
newsamp = -32768 ;
if (errordelta < 0)
errordelta += 0x10 ;
byte = (byte << 4) | (errordelta & 0xF) ;
if (k % 2)
{ pms->block [blockindx++] = byte ;
byte = 0 ;
} ;
idelta [0] = (idelta [0] * AdaptationTable [errordelta]) >> 8 ;
if (idelta [0] < 16)
idelta [0] = 16 ;
pms->samples [k] = newsamp ;
} ;
}
else
{ /* Stereo file. */
pms->block [0] = bpred [0] ;
pms->block [1] = bpred [1] ;
pms->block [2] = idelta [0] & 0xFF ;
pms->block [3] = idelta [0] >> 8 ;
pms->block [4] = idelta [1] & 0xFF ;
pms->block [5] = idelta [1] >> 8 ;
pms->block [6] = pms->samples [2] & 0xFF ;
pms->block [7] = pms->samples [2] >> 8 ;
pms->block [8] = pms->samples [3] & 0xFF ;
pms->block [9] = pms->samples [3] >> 8 ;
pms->block [10] = pms->samples [0] & 0xFF ;
pms->block [11] = pms->samples [0] >> 8 ;
pms->block [12] = pms->samples [1] & 0xFF ;
pms->block [13] = pms->samples [1] >> 8 ;
blockindx = 14 ;
byte = 0 ;
chan = 1 ;
for (k = 4 ; k < 2 * pms->samplesperblock ; k++)
{ chan = k & 1 ;
predict = (pms->samples [k-2] * AdaptCoeff1 [bpred [chan]] + pms->samples [k-4] * AdaptCoeff2 [bpred [chan]]) >> 8 ;
errordelta = (pms->samples [k] - predict) / idelta [chan] ;
if (errordelta < -8)
errordelta = -8 ;
else if (errordelta > 7)
errordelta = 7 ;
newsamp = predict + (idelta [chan] * errordelta) ;
if (newsamp > 32767)
newsamp = 32767 ;
else if (newsamp < -32768)
newsamp = -32768 ;
if (errordelta < 0)
errordelta += 0x10 ;
byte = (byte << 4) | (errordelta & 0xF) ;
if (chan)
{ pms->block [blockindx++] = byte ;
byte = 0 ;
} ;
idelta [chan] = (idelta [chan] * AdaptationTable [errordelta]) >> 8 ;
if (idelta [chan] < 16)
idelta [chan] = 16 ;
pms->samples [k] = newsamp ;
} ;
} ;
/* Write the block to disk. */
if ((k = psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize)
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pms->blocksize) ;
memset (pms->samples, 0, pms->samplesperblock * sizeof (short)) ;
pms->blockcount ++ ;
pms->samplecount = 0 ;
return 1 ;
} /* msadpcm_encode_block */
static sf_count_t
msadpcm_write_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, const short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ count = (pms->samplesperblock - pms->samplecount) * pms->channels ;
if (count > len - indx)
count = len - indx ;
memcpy (&(pms->samples [pms->samplecount * pms->channels]), &(ptr [total]), count * sizeof (short)) ;
indx += count ;
pms->samplecount += count / pms->channels ;
total = indx ;
if (pms->samplecount >= pms->samplesperblock)
msadpcm_encode_block (psf, pms) ;
} ;
return total ;
} /* msadpcm_write_block */
static sf_count_t
msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
int writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
while (len > 0)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = msadpcm_write_block (psf, pms, ptr, writecount) ;
total += count ;
len -= count ;
if (count != writecount)
break ;
} ;
return total ;
} /* msadpcm_write_s */
static sf_count_t
msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = ptr [total + k] >> 16 ;
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* msadpcm_write_i */
static sf_count_t
msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = lrintf (normfact * ptr [total + k]) ;
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* msadpcm_write_f */
static sf_count_t
msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
double normfact ;
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
sptr [k] = lrint (normfact * ptr [total + k]) ;
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* msadpcm_write_d */
/*========================================================================================
*/
static int
msadpcm_close (SF_PRIVATE *psf)
{ MSADPCM_PRIVATE *pms ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
if (psf->mode == SFM_WRITE)
{ /* Now we know static int for certain the length of the file we can
** re-write the header.
*/
if (pms->samplecount && pms->samplecount < pms->samplesperblock)
msadpcm_encode_block (psf, pms) ;
} ;
return 0 ;
} /* msadpcm_close */
/*========================================================================================
** Static functions.
*/
/*----------------------------------------------------------------------------------------
** Choosing the block predictor.
** Each block requires a predictor and an idelta for each channel.
** The predictor is in the range [0..6] which is an indx into the two AdaptCoeff tables.
** The predictor is chosen by trying all of the possible predictors on a small set of
** samples at the beginning of the block. The predictor with the smallest average
** abs (idelta) is chosen as the best predictor for this block.
** The value of idelta is chosen to to give a 4 bit code value of +/- 4 (approx. half the
** max. code value). If the average abs (idelta) is zero, the sixth predictor is chosen.
** If the value of idelta is less then 16 it is set to 16.
**
** Microsoft uses an IDELTA_COUNT (number of sample pairs used to choose best predictor)
** value of 3. The best possible results would be obtained by using all the samples to
** choose the predictor.
*/
#define IDELTA_COUNT 3
static void
choose_predictor (unsigned int channels, short *data, int *block_pred, int *idelta)
{ unsigned int chan, k, bpred, idelta_sum, best_bpred, best_idelta ;
for (chan = 0 ; chan < channels ; chan++)
{ best_bpred = best_idelta = 0 ;
for (bpred = 0 ; bpred < 7 ; bpred++)
{ idelta_sum = 0 ;
for (k = 2 ; k < 2 + IDELTA_COUNT ; k++)
idelta_sum += abs (data [k * channels] - ((data [(k - 1) * channels] * AdaptCoeff1 [bpred] + data [(k - 2) * channels] * AdaptCoeff2 [bpred]) >> 8)) ;
idelta_sum /= (4 * IDELTA_COUNT) ;
if (bpred == 0 || idelta_sum < best_idelta)
{ best_bpred = bpred ;
best_idelta = idelta_sum ;
} ;
if (! idelta_sum)
{ best_bpred = bpred ;
best_idelta = 16 ;
break ;
} ;
} ; /* for bpred ... */
if (best_idelta < 16)
best_idelta = 16 ;
block_pred [chan] = best_bpred ;
idelta [chan] = best_idelta ;
} ;
return ;
} /* choose_predictor */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a98908a3-5305-4935-872b-77d6a86c330f
*/

367
libs/libsndfile/src/nist.c Normal file
View File

@@ -0,0 +1,367 @@
/*
** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** Some of the information used to read NIST files was gleaned from
** reading the code of Bill Schottstaedt's sndlib library
** ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz
** However, no code from that package was used.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*------------------------------------------------------------------------------
*/
#define NIST_HEADER_LENGTH 1024
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int nist_close (SF_PRIVATE *psf) ;
static int nist_write_header (SF_PRIVATE *psf, int calc_length) ;
static int nist_read_header (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
*/
int
nist_open (SF_PRIVATE *psf)
{ int error ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = nist_read_header (psf)))
return error ;
} ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_NIST)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)
psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
psf->sf.frames = 0 ;
if ((error = nist_write_header (psf, SF_FALSE)))
return error ;
psf->write_header = nist_write_header ;
} ;
psf->container_close = nist_close ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_PCM_32 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_ULAW :
error = ulaw_init (psf) ;
break ;
case SF_FORMAT_ALAW :
error = alaw_init (psf) ;
break ;
default : error = SFE_UNIMPLEMENTED ;
break ;
} ;
return error ;
} /* nist_open */
/*------------------------------------------------------------------------------
*/
static char bad_header [] =
{ 'N', 'I', 'S', 'T', '_', '1', 'A', 0x0d, 0x0a,
' ', ' ', ' ', '1', '0', '2', '4', 0x0d, 0x0a,
0
} ;
static int
nist_read_header (SF_PRIVATE *psf)
{ char *psf_header ;
int bitwidth = 0, bytes = 0, count, encoding ;
char str [64], *cptr ;
long samples ;
psf->sf.format = SF_FORMAT_NIST ;
psf_header = psf->u.cbuf ;
if (sizeof (psf->header) <= NIST_HEADER_LENGTH)
return SFE_INTERNAL ;
/* Go to start of file and read in the whole header. */
psf_binheader_readf (psf, "pb", 0, psf_header, NIST_HEADER_LENGTH) ;
/* Header is a string, so make sure it is null terminated. */
psf_header [NIST_HEADER_LENGTH] = 0 ;
/* Now trim the header after the end marker. */
if ((cptr = strstr (psf_header, "end_head")))
{ cptr += strlen ("end_head") + 1 ;
cptr [0] = 0 ;
} ;
if (strstr (psf_header, bad_header) == psf_header)
return SFE_NIST_CRLF_CONVERISON ;
/* Make sure its a NIST file. */
if (strstr (psf_header, "NIST_1A\n") != psf_header)
{ psf_log_printf (psf, "Not a NIST file.\n") ;
return SFE_NIST_BAD_HEADER ;
} ;
if (sscanf (psf_header, "NIST_1A\n%d\n", &count) == 1)
psf->dataoffset = count ;
else
{ psf_log_printf (psf, "*** Suspicious header length.\n") ;
psf->dataoffset = NIST_HEADER_LENGTH ;
} ;
/* Determine sample encoding, start by assuming PCM. */
encoding = SF_FORMAT_PCM_U8 ;
if ((cptr = strstr (psf_header, "sample_coding -s")))
{ sscanf (cptr, "sample_coding -s%d %63s", &count, str) ;
if (strcmp (str, "pcm") == 0)
encoding = SF_FORMAT_PCM_U8 ;
else if (strcmp (str, "alaw") == 0)
encoding = SF_FORMAT_ALAW ;
else if ((strcmp (str, "ulaw") == 0) || (strcmp (str, "mu-law") == 0))
encoding = SF_FORMAT_ULAW ;
else
{ psf_log_printf (psf, "*** Unknown encoding : %s\n", str) ;
encoding = 0 ;
} ;
} ;
if ((cptr = strstr (psf_header, "channel_count -i ")))
sscanf (cptr, "channel_count -i %d", &(psf->sf.channels)) ;
if ((cptr = strstr (psf_header, "sample_rate -i ")))
sscanf (cptr, "sample_rate -i %d", &(psf->sf.samplerate)) ;
if ((cptr = strstr (psf_header, "sample_count -i ")))
{ sscanf (psf_header, "sample_count -i %ld", &samples) ;
psf->sf.frames = samples ;
} ;
if ((cptr = strstr (psf_header, "sample_n_bytes -i ")))
sscanf (cptr, "sample_n_bytes -i %d", &(psf->bytewidth)) ;
/* Default endian-ness (for 8 bit, u-law, A-law. */
psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
/* This is where we figure out endian-ness. */
if ((cptr = strstr (psf_header, "sample_byte_format -s")))
{ sscanf (cptr, "sample_byte_format -s%d %8s", &bytes, str) ;
if (bytes > 1)
{ if (psf->bytewidth == 0)
psf->bytewidth = bytes ;
else if (psf->bytewidth != bytes)
{ psf_log_printf (psf, "psf->bytewidth (%d) != bytes (%d)\n", psf->bytewidth, bytes) ;
return SFE_NIST_BAD_ENCODING ;
} ;
if (strstr (str, "01") == str)
psf->endian = SF_ENDIAN_LITTLE ;
else if (strstr (str, "10"))
psf->endian = SF_ENDIAN_BIG ;
else
{ psf_log_printf (psf, "Weird endian-ness : %s\n", str) ;
return SFE_NIST_BAD_ENCODING ;
} ;
} ;
psf->sf.format |= psf->endian ;
} ;
if ((cptr = strstr (psf_header, "sample_sig_bits -i ")))
sscanf (cptr, "sample_sig_bits -i %d", &bitwidth) ;
if (strstr (psf_header, "channels_interleaved -s5 FALSE"))
{ psf_log_printf (psf, "Non-interleaved data unsupported.\n", str) ;
return SFE_NIST_BAD_ENCODING ;
} ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
psf->datalength = psf->filelength - psf->dataoffset ;
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
if (encoding == SF_FORMAT_PCM_U8)
{ switch (psf->bytewidth)
{ case 1 :
psf->sf.format |= SF_FORMAT_PCM_S8 ;
break ;
case 2 :
psf->sf.format |= SF_FORMAT_PCM_16 ;
break ;
case 3 :
psf->sf.format |= SF_FORMAT_PCM_24 ;
break ;
case 4 :
psf->sf.format |= SF_FORMAT_PCM_32 ;
break ;
default : break ;
} ;
}
else if (encoding != 0)
psf->sf.format |= encoding ;
else
return SFE_UNIMPLEMENTED ;
return 0 ;
} /* nist_read_header */
static int
nist_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
nist_write_header (psf, SF_TRUE) ;
return 0 ;
} /* nist_close */
/*=========================================================================
*/
static int
nist_write_header (SF_PRIVATE *psf, int calc_length)
{ const char *end_str ;
long samples ;
sf_count_t current ;
current = psf_ftell (psf) ;
if (calc_length)
{ psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->dataend)
psf->datalength -= psf->filelength - psf->dataend ;
if (psf->bytewidth > 0)
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
} ;
if (psf->endian == SF_ENDIAN_BIG)
end_str = "10" ;
else if (psf->endian == SF_ENDIAN_LITTLE)
end_str = "01" ;
else
end_str = "error" ;
/* Clear the whole header. */
memset (psf->header, 0, sizeof (psf->header)) ;
psf->headindex = 0 ;
psf_fseek (psf, 0, SEEK_SET) ;
psf_asciiheader_printf (psf, "NIST_1A\n 1024\n") ;
psf_asciiheader_printf (psf, "channel_count -i %d\n", psf->sf.channels) ;
psf_asciiheader_printf (psf, "sample_rate -i %d\n", psf->sf.samplerate) ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n") ;
psf_asciiheader_printf (psf, "sample_n_bytes -i 1\n"
"sample_sig_bits -i 8\n") ;
break ;
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_PCM_32 :
psf_asciiheader_printf (psf, "sample_n_bytes -i %d\n", psf->bytewidth) ;
psf_asciiheader_printf (psf, "sample_sig_bits -i %d\n", psf->bytewidth * 8) ;
psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n"
"sample_byte_format -s%d %s\n", psf->bytewidth, end_str) ;
break ;
case SF_FORMAT_ALAW :
psf_asciiheader_printf (psf, "sample_coding -s4 alaw\n") ;
psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ;
break ;
case SF_FORMAT_ULAW :
psf_asciiheader_printf (psf, "sample_coding -s4 ulaw\n") ;
psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
psf->dataoffset = NIST_HEADER_LENGTH ;
/* Fix this */
samples = psf->sf.frames ;
psf_asciiheader_printf (psf, "sample_count -i %ld\n", samples) ;
psf_asciiheader_printf (psf, "end_head\n") ;
/* Zero fill to dataoffset. */
psf_binheader_writef (psf, "z", (size_t) (NIST_HEADER_LENGTH - psf->headindex)) ;
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* nist_write_header */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: b45ed85d-9e22-4ad9-b78c-4b58b67152a8
*/

44
libs/libsndfile/src/ogg.c Normal file
View File

@@ -0,0 +1,44 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software ; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation ; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program ; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
int
ogg_open (SF_PRIVATE *psf)
{ if (psf)
return SFE_UNIMPLEMENTED ;
return (psf && 0) ;
} /* ogg_open */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 9ff1fe9c-629e-4e9c-9ef5-3d0eb1e427a0
*/

843
libs/libsndfile/src/paf.c Normal file
View File

@@ -0,0 +1,843 @@
/*
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define FAP_MARKER (MAKE_MARKER ('f', 'a', 'p', ' '))
#define PAF_MARKER (MAKE_MARKER (' ', 'p', 'a', 'f'))
/*------------------------------------------------------------------------------
** Other defines.
*/
#define PAF_HEADER_LENGTH 2048
#define PAF24_SAMPLES_PER_BLOCK 10
#define PAF24_BLOCK_SIZE 32
/*------------------------------------------------------------------------------
** Typedefs.
*/
typedef struct
{ int version ;
int endianness ;
int samplerate ;
int format ;
int channels ;
int source ;
} PAF_FMT ;
typedef struct
{ int max_blocks, channels, samplesperblock, blocksize ;
int read_block, write_block, read_count, write_count ;
sf_count_t sample_count ;
int *samples ;
unsigned char *block ;
#if HAVE_FLEXIBLE_ARRAY
int data [] ; /* ISO C99 struct flexible array. */
#else
int data [1] ; /* This is a hack and may not work. */
#endif
} PAF24_PRIVATE ;
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int paf24_init (SF_PRIVATE *psf) ;
static int paf_read_header (SF_PRIVATE *psf) ;
static int paf_write_header (SF_PRIVATE *psf, int calc_length) ;
static sf_count_t paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t paf24_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static sf_count_t paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
enum
{ PAF_PCM_16 = 0,
PAF_PCM_24 = 1,
PAF_PCM_S8 = 2
} ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
paf_open (SF_PRIVATE *psf)
{ int subformat, error, endian ;
psf->dataoffset = PAF_HEADER_LENGTH ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = paf_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF)
return SFE_BAD_OPEN_FORMAT ;
endian = psf->sf.format & SF_FORMAT_ENDMASK ;
/* PAF is by default big endian. */
psf->endian = SF_ENDIAN_BIG ;
if (endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && (endian == SF_ENDIAN_CPU)))
psf->endian = SF_ENDIAN_LITTLE ;
if ((error = paf_write_header (psf, SF_FALSE)))
return error ;
psf->write_header = paf_write_header ;
} ;
switch (subformat)
{ case SF_FORMAT_PCM_S8 :
psf->bytewidth = 1 ;
error = pcm_init (psf) ;
break ;
case SF_FORMAT_PCM_16 :
psf->bytewidth = 2 ;
error = pcm_init (psf) ;
break ;
case SF_FORMAT_PCM_24 :
/* No bytewidth because of whacky 24 bit encoding. */
error = paf24_init (psf) ;
break ;
default : return SFE_PAF_UNKNOWN_FORMAT ;
} ;
return error ;
} /* paf_open */
/*------------------------------------------------------------------------------
*/
static int
paf_read_header (SF_PRIVATE *psf)
{ PAF_FMT paf_fmt ;
int marker ;
memset (&paf_fmt, 0, sizeof (paf_fmt)) ;
psf_binheader_readf (psf, "pm", 0, &marker) ;
psf_log_printf (psf, "Signature : '%M'\n", marker) ;
if (marker == PAF_MARKER)
{ psf_binheader_readf (psf, "E444444", &(paf_fmt.version), &(paf_fmt.endianness),
&(paf_fmt.samplerate), &(paf_fmt.format), &(paf_fmt.channels), &(paf_fmt.source)) ;
}
else if (marker == FAP_MARKER)
{ psf_binheader_readf (psf, "e444444", &(paf_fmt.version), &(paf_fmt.endianness),
&(paf_fmt.samplerate), &(paf_fmt.format), &(paf_fmt.channels), &(paf_fmt.source)) ;
}
else
return SFE_PAF_NO_MARKER ;
psf_log_printf (psf, "Version : %d\n", paf_fmt.version) ;
if (paf_fmt.version != 0)
{ psf_log_printf (psf, "*** Bad version number. should be zero.\n") ;
return SFE_PAF_VERSION ;
} ;
psf_log_printf (psf, "Sample Rate : %d\n", paf_fmt.samplerate) ;
psf_log_printf (psf, "Channels : %d\n", paf_fmt.channels) ;
psf_log_printf (psf, "Endianness : %d => ", paf_fmt.endianness) ;
if (paf_fmt.endianness)
{ psf_log_printf (psf, "Little\n", paf_fmt.endianness) ;
psf->endian = SF_ENDIAN_LITTLE ;
}
else
{ psf_log_printf (psf, "Big\n", paf_fmt.endianness) ;
psf->endian = SF_ENDIAN_BIG ;
} ;
if (psf->filelength < PAF_HEADER_LENGTH)
return SFE_PAF_SHORT_HEADER ;
psf->datalength = psf->filelength - psf->dataoffset ;
psf_binheader_readf (psf, "p", (int) psf->dataoffset) ;
psf->sf.samplerate = paf_fmt.samplerate ;
psf->sf.channels = paf_fmt.channels ;
/* Only fill in type major. */
psf->sf.format = SF_FORMAT_PAF ;
psf_log_printf (psf, "Format : %d => ", paf_fmt.format) ;
/* PAF is by default big endian. */
psf->sf.format |= paf_fmt.endianness ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
switch (paf_fmt.format)
{ case PAF_PCM_S8 :
psf_log_printf (psf, "8 bit linear PCM\n") ;
psf->bytewidth = 1 ;
psf->sf.format |= SF_FORMAT_PCM_S8 ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
psf->sf.frames = psf->datalength / psf->blockwidth ;
break ;
case PAF_PCM_16 :
psf_log_printf (psf, "16 bit linear PCM\n") ;
psf->bytewidth = 2 ;
psf->sf.format |= SF_FORMAT_PCM_16 ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
psf->sf.frames = psf->datalength / psf->blockwidth ;
break ;
case PAF_PCM_24 :
psf_log_printf (psf, "24 bit linear PCM\n") ;
psf->bytewidth = 3 ;
psf->sf.format |= SF_FORMAT_PCM_24 ;
psf->blockwidth = 0 ;
psf->sf.frames = PAF24_SAMPLES_PER_BLOCK * psf->datalength /
(PAF24_BLOCK_SIZE * psf->sf.channels) ;
break ;
default : psf_log_printf (psf, "Unknown\n") ;
return SFE_PAF_UNKNOWN_FORMAT ;
break ;
} ;
psf_log_printf (psf, "Source : %d => ", paf_fmt.source) ;
switch (paf_fmt.source)
{ case 1 : psf_log_printf (psf, "Analog Recording\n") ;
break ;
case 2 : psf_log_printf (psf, "Digital Transfer\n") ;
break ;
case 3 : psf_log_printf (psf, "Multi-track Mixdown\n") ;
break ;
case 5 : psf_log_printf (psf, "Audio Resulting From DSP Processing\n") ;
break ;
default : psf_log_printf (psf, "Unknown\n") ;
break ;
} ;
return 0 ;
} /* paf_read_header */
static int
paf_write_header (SF_PRIVATE *psf, int calc_length)
{ int paf_format ;
/* PAF header already written so no need to re-write. */
if (psf_ftell (psf) >= PAF_HEADER_LENGTH)
return 0 ;
psf->dataoffset = PAF_HEADER_LENGTH ;
psf->dataoffset = PAF_HEADER_LENGTH ;
/* Prevent compiler warning. */
calc_length = calc_length ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
paf_format = PAF_PCM_S8 ;
break ;
case SF_FORMAT_PCM_16 :
paf_format = PAF_PCM_16 ;
break ;
case SF_FORMAT_PCM_24 :
paf_format = PAF_PCM_24 ;
break ;
default : return SFE_PAF_UNKNOWN_FORMAT ;
} ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
if (psf->endian == SF_ENDIAN_BIG)
{ /* Marker, version, endianness, samplerate */
psf_binheader_writef (psf, "Em444", PAF_MARKER, 0, 0, psf->sf.samplerate) ;
/* format, channels, source */
psf_binheader_writef (psf, "E444", paf_format, psf->sf.channels, 0) ;
}
else if (psf->endian == SF_ENDIAN_LITTLE)
{ /* Marker, version, endianness, samplerate */
psf_binheader_writef (psf, "em444", FAP_MARKER, 0, 1, psf->sf.samplerate) ;
/* format, channels, source */
psf_binheader_writef (psf, "e444", paf_format, psf->sf.channels, 0) ;
} ;
/* Zero fill to dataoffset. */
psf_binheader_writef (psf, "z", (size_t) (psf->dataoffset - psf->headindex)) ;
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
return psf->error ;
} /* paf_write_header */
/*===============================================================================
** 24 bit PAF files have a really weird encoding.
** For a mono file, 10 samples (each being 3 bytes) are packed into a 32 byte
** block. The 8 ints in this 32 byte block are then endian swapped (as ints)
** if necessary before being written to disk.
** For a stereo file, blocks of 10 samples from the same channel are encoded
** into 32 bytes as for the mono case. The 32 byte blocks are then interleaved
** on disk.
** Reading has to reverse the above process :-).
** Weird!!!
**
** The code below attempts to gain efficiency while maintaining readability.
*/
static int paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) ;
static int paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) ;
static int paf24_close (SF_PRIVATE *psf) ;
static int
paf24_init (SF_PRIVATE *psf)
{ PAF24_PRIVATE *ppaf24 ;
int paf24size ;
paf24size = sizeof (PAF24_PRIVATE) + psf->sf.channels *
(PAF24_BLOCK_SIZE + PAF24_SAMPLES_PER_BLOCK * sizeof (int)) ;
/*
** Not exatly sure why this needs to be here but the tests
** fail without it.
*/
psf->last_op = 0 ;
if (! (psf->fdata = malloc (paf24size)))
return SFE_MALLOC_FAILED ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
memset (ppaf24, 0, paf24size) ;
ppaf24->channels = psf->sf.channels ;
ppaf24->samples = ppaf24->data ;
ppaf24->block = (unsigned char*) (ppaf24->data + PAF24_SAMPLES_PER_BLOCK * ppaf24->channels) ;
ppaf24->blocksize = PAF24_BLOCK_SIZE * ppaf24->channels ;
ppaf24->samplesperblock = PAF24_SAMPLES_PER_BLOCK ;
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
{ paf24_read_block (psf, ppaf24) ; /* Read first block. */
psf->read_short = paf24_read_s ;
psf->read_int = paf24_read_i ;
psf->read_float = paf24_read_f ;
psf->read_double = paf24_read_d ;
} ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->write_short = paf24_write_s ;
psf->write_int = paf24_write_i ;
psf->write_float = paf24_write_f ;
psf->write_double = paf24_write_d ;
} ;
psf->seek = paf24_seek ;
psf->container_close = paf24_close ;
psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->datalength % PAF24_BLOCK_SIZE)
{ if (psf->mode == SFM_READ)
psf_log_printf (psf, "*** Warning : file seems to be truncated.\n") ;
ppaf24->max_blocks = psf->datalength / ppaf24->blocksize + 1 ;
}
else
ppaf24->max_blocks = psf->datalength / ppaf24->blocksize ;
ppaf24->read_block = 0 ;
if (psf->mode == SFM_RDWR)
ppaf24->write_block = ppaf24->max_blocks ;
else
ppaf24->write_block = 0 ;
psf->sf.frames = ppaf24->samplesperblock * ppaf24->max_blocks ;
ppaf24->sample_count = psf->sf.frames ;
return 0 ;
} /* paf24_init */
static sf_count_t
paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{ PAF24_PRIVATE *ppaf24 ;
int newblock, newsample ;
if (psf->fdata == NULL)
{ psf->error = SFE_INTERNAL ;
return PSF_SEEK_ERROR ;
} ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
if (mode == SFM_READ && ppaf24->write_count > 0)
paf24_write_block (psf, ppaf24) ;
newblock = offset / ppaf24->samplesperblock ;
newsample = offset % ppaf24->samplesperblock ;
switch (mode)
{ case SFM_READ :
if (psf->last_op == SFM_WRITE && ppaf24->write_count)
paf24_write_block (psf, ppaf24) ;
psf_fseek (psf, psf->dataoffset + newblock * ppaf24->blocksize, SEEK_SET) ;
ppaf24->read_block = newblock ;
paf24_read_block (psf, ppaf24) ;
ppaf24->read_count = newsample ;
break ;
case SFM_WRITE :
if (offset > ppaf24->sample_count)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
if (psf->last_op == SFM_WRITE && ppaf24->write_count)
paf24_write_block (psf, ppaf24) ;
psf_fseek (psf, psf->dataoffset + newblock * ppaf24->blocksize, SEEK_SET) ;
ppaf24->write_block = newblock ;
paf24_read_block (psf, ppaf24) ;
ppaf24->write_count = newsample ;
break ;
default :
psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
return newblock * ppaf24->samplesperblock + newsample ;
} /* paf24_seek */
static int
paf24_close (SF_PRIVATE *psf)
{ PAF24_PRIVATE *ppaf24 ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (ppaf24->write_count > 0)
paf24_write_block (psf, ppaf24) ;
} ;
return 0 ;
} /* paf24_close */
/*---------------------------------------------------------------------------
*/
static int
paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24)
{ int k, channel ;
unsigned char *cptr ;
ppaf24->read_block ++ ;
ppaf24->read_count = 0 ;
if (ppaf24->read_block * ppaf24->samplesperblock > ppaf24->sample_count)
{ memset (ppaf24->samples, 0, ppaf24->samplesperblock * ppaf24->channels) ;
return 1 ;
} ;
/* Read the block. */
if ((k = psf_fread (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, ppaf24->blocksize) ;
if (CPU_IS_LITTLE_ENDIAN)
{ /* Do endian swapping if necessary. */
if (psf->endian == SF_ENDIAN_BIG)
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
/* Unpack block. */
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
{ channel = k % ppaf24->channels ;
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ;
} ;
}
else
{ /* Do endian swapping if necessary. */
if (psf->endian == SF_ENDIAN_BIG)
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
/* Unpack block. */
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
{ channel = k % ppaf24->channels ;
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ;
} ;
} ;
return 1 ;
} /* paf24_read_block */
static int
paf24_read (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, int *ptr, int len)
{ int count, total = 0 ;
while (total < len)
{ if (ppaf24->read_block * ppaf24->samplesperblock >= ppaf24->sample_count)
{ memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ;
return total ;
} ;
if (ppaf24->read_count >= ppaf24->samplesperblock)
paf24_read_block (psf, ppaf24) ;
count = (ppaf24->samplesperblock - ppaf24->read_count) * ppaf24->channels ;
count = (len - total > count) ? count : len - total ;
memcpy (&(ptr [total]), &(ppaf24->samples [ppaf24->read_count * ppaf24->channels]), count * sizeof (int)) ;
total += count ;
ppaf24->read_count += count / ppaf24->channels ;
} ;
return total ;
} /* paf24_read */
static sf_count_t
paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = paf24_read (psf, ppaf24, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = iptr [k] >> 16 ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* paf24_read_s */
static sf_count_t
paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int total ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
total = paf24_read (psf, ppaf24, ptr, len) ;
return total ;
} /* paf24_read_i */
static sf_count_t
paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = paf24_read (psf, ppaf24, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * iptr [k] ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* paf24_read_f */
static sf_count_t
paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = paf24_read (psf, ppaf24, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * iptr [k] ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* paf24_read_d */
/*---------------------------------------------------------------------------
*/
static int
paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24)
{ int k, nextsample, channel ;
unsigned char *cptr ;
/* First pack block. */
if (CPU_IS_LITTLE_ENDIAN)
{ for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
{ channel = k % ppaf24->channels ;
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
nextsample = ppaf24->samples [k] >> 8 ;
cptr [0] = nextsample ;
cptr [1] = nextsample >> 8 ;
cptr [2] = nextsample >> 16 ;
} ;
/* Do endian swapping if necessary. */
if (psf->endian == SF_ENDIAN_BIG)
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
}
else if (CPU_IS_BIG_ENDIAN)
{ /* This is correct. */
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
{ channel = k % ppaf24->channels ;
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
nextsample = ppaf24->samples [k] >> 8 ;
cptr [0] = nextsample ;
cptr [1] = nextsample >> 8 ;
cptr [2] = nextsample >> 16 ;
} ;
if (psf->endian == SF_ENDIAN_BIG)
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
} ;
/* Write block to disk. */
if ((k = psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize)
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, ppaf24->blocksize) ;
if (ppaf24->sample_count < ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count)
ppaf24->sample_count = ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count ;
if (ppaf24->write_count == ppaf24->samplesperblock)
{ ppaf24->write_block ++ ;
ppaf24->write_count = 0 ;
} ;
return 1 ;
} /* paf24_write_block */
static int
paf24_write (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, const int *ptr, int len)
{ int count, total = 0 ;
while (total < len)
{ count = (ppaf24->samplesperblock - ppaf24->write_count) * ppaf24->channels ;
if (count > len - total)
count = len - total ;
memcpy (&(ppaf24->samples [ppaf24->write_count * ppaf24->channels]), &(ptr [total]), count * sizeof (int)) ;
total += count ;
ppaf24->write_count += count / ppaf24->channels ;
if (ppaf24->write_count >= ppaf24->samplesperblock)
paf24_write_block (psf, ppaf24) ;
} ;
return total ;
} /* paf24_write */
static sf_count_t
paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int *iptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = ptr [total + k] << 16 ;
count = paf24_write (psf, ppaf24, iptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* paf24_write_s */
static sf_count_t
paf24_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int writecount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
while (len > 0)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = paf24_write (psf, ppaf24, ptr, writecount) ;
total += count ;
len -= count ;
if (count != writecount)
break ;
} ;
return total ;
} /* paf24_write_i */
static sf_count_t
paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int *iptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = lrintf (normfact * ptr [total + k]) ;
count = paf24_write (psf, ppaf24, iptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* paf24_write_f */
static sf_count_t
paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int *iptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = lrint (normfact * ptr [total+k]) ;
count = paf24_write (psf, ppaf24, iptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* paf24_write_d */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 477a5308-451e-4bbd-bab4-fab6caa4e884
*/

2899
libs/libsndfile/src/pcm.c Normal file

File diff suppressed because it is too large Load Diff

199
libs/libsndfile/src/pvf.c Normal file
View File

@@ -0,0 +1,199 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define PVF1_MARKER (MAKE_MARKER ('P', 'V', 'F', '1'))
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int pvf_close (SF_PRIVATE *psf) ;
static int pvf_write_header (SF_PRIVATE *psf, int calc_length) ;
static int pvf_read_header (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
pvf_open (SF_PRIVATE *psf)
{ int subformat ;
int error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = pvf_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PVF)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = SF_ENDIAN_BIG ;
if (pvf_write_header (psf, SF_FALSE))
return psf->error ;
psf->write_header = pvf_write_header ;
} ;
psf->container_close = pvf_close ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
switch (subformat)
{ case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */
error = pcm_init (psf) ;
break ;
default : break ;
} ;
return error ;
} /* pvf_open */
/*------------------------------------------------------------------------------
*/
static int
pvf_close (SF_PRIVATE *psf)
{
psf = psf ;
return 0 ;
} /* pvf_close */
static int
pvf_write_header (SF_PRIVATE *psf, int calc_length)
{ sf_count_t current ;
if (psf->pipeoffset > 0)
return 0 ;
calc_length = calc_length ; /* Avoid a compiler warning. */
current = psf_ftell (psf) ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
if (psf->is_pipe == SF_FALSE)
psf_fseek (psf, 0, SEEK_SET) ;
LSF_SNPRINTF ((char*) psf->header, sizeof (psf->header), "PVF1\n%d %d %d\n",
psf->sf.channels, psf->sf.samplerate, psf->bytewidth * 8) ;
psf->headindex = strlen ((char*) psf->header) ;
/* Header construction complete so write it out. */
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* pvf_write_header */
static int
pvf_read_header (SF_PRIVATE *psf)
{ char buffer [32] ;
int marker, channels, samplerate, bitwidth ;
psf_binheader_readf (psf, "pmj", 0, &marker, 1) ;
psf_log_printf (psf, "%M\n", marker) ;
if (marker != PVF1_MARKER)
return SFE_PVF_NO_PVF1 ;
/* Grab characters up until a newline which is replaced by an EOS. */
psf_binheader_readf (psf, "G", buffer, sizeof (buffer)) ;
if (sscanf (buffer, "%d %d %d", &channels, &samplerate, &bitwidth) != 3)
return SFE_PVF_BAD_HEADER ;
psf_log_printf (psf, " Channels : %d\n Sample rate : %d\n Bit width : %d\n",
channels, samplerate, bitwidth) ;
psf->sf.channels = channels ;
psf->sf.samplerate = samplerate ;
switch (bitwidth)
{ case 8 :
psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_S8 ;
psf->bytewidth = 1 ;
break ;
case 16 :
psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
break ;
case 32 :
psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_32 ;
psf->bytewidth = 4 ;
break ;
default :
return SFE_PVF_BAD_BITWIDTH ;
} ;
psf->dataoffset = psf_ftell (psf) ;
psf_log_printf (psf, " Data Offset : %D\n", psf->dataoffset) ;
psf->endian = SF_ENDIAN_BIG ;
psf->datalength = psf->filelength - psf->dataoffset ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
if (! psf->sf.frames && psf->blockwidth)
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
return 0 ;
} /* pvf_read_header */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 20a26761-8bc1-41d7-b1f3-9793bf3d9864
*/

111
libs/libsndfile/src/raw.c Normal file
View File

@@ -0,0 +1,111 @@
/*
** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include "sndfile.h"
#include "common.h"
/*------------------------------------------------------------------------------
** Public function.
*/
int
raw_open (SF_PRIVATE *psf)
{ int subformat, error = SFE_NO_ERROR ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
psf->endian = SF_ENDIAN_BIG ;
else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
psf->endian = SF_ENDIAN_LITTLE ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
psf->dataoffset = 0 ;
psf->datalength = psf->filelength ;
switch (subformat)
{ case SF_FORMAT_PCM_S8 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_PCM_U8 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_PCM_32 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_ULAW :
error = ulaw_init (psf) ;
break ;
case SF_FORMAT_ALAW :
error = alaw_init (psf) ;
break ;
case SF_FORMAT_GSM610 :
error = gsm610_init (psf) ;
break ;
/* Lite remove start */
case SF_FORMAT_FLOAT :
error = float32_init (psf) ;
break ;
case SF_FORMAT_DOUBLE :
error = double64_init (psf) ;
break ;
case SF_FORMAT_DWVW_12 :
error = dwvw_init (psf, 12) ;
break ;
case SF_FORMAT_DWVW_16 :
error = dwvw_init (psf, 16) ;
break ;
case SF_FORMAT_DWVW_24 :
error = dwvw_init (psf, 24) ;
break ;
case SF_FORMAT_VOX_ADPCM :
error = vox_adpcm_init (psf) ;
break ;
/* Lite remove end */
default : return SFE_BAD_OPEN_FORMAT ;
} ;
return error ;
} /* raw_open */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f0066de7-d6ce-4f36-a1e0-e475c07d4e1a
*/

326
libs/libsndfile/src/rx2.c Normal file
View File

@@ -0,0 +1,326 @@
/*
** Copyright (C) 2001-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#if (ENABLE_EXPERIMENTAL_CODE == 0)
int
rx2_open (SF_PRIVATE *psf)
{ if (psf)
return SFE_UNIMPLEMENTED ;
return (psf && 0) ;
} /* rx2_open */
#else
/*------------------------------------------------------------------------------
* Macros to handle big/little endian issues.
*/
#define CAT_MARKER (MAKE_MARKER ('C', 'A', 'T', ' '))
#define GLOB_MARKER (MAKE_MARKER ('G', 'L', 'O', 'B'))
#define RECY_MARKER (MAKE_MARKER ('R', 'E', 'C', 'Y'))
#define SLCL_MARKER (MAKE_MARKER ('S', 'L', 'C', 'L'))
#define SLCE_MARKER (MAKE_MARKER ('S', 'L', 'C', 'E'))
#define DEVL_MARKER (MAKE_MARKER ('D', 'E', 'V', 'L'))
#define TRSH_MARKER (MAKE_MARKER ('T', 'R', 'S', 'H'))
#define EQ_MARKER (MAKE_MARKER ('E', 'Q', ' ', ' '))
#define COMP_MARKER (MAKE_MARKER ('C', 'O', 'M', 'P'))
#define SINF_MARKER (MAKE_MARKER ('S', 'I', 'N', 'F'))
#define SDAT_MARKER (MAKE_MARKER ('S', 'D', 'A', 'T'))
/*------------------------------------------------------------------------------
* Typedefs for file chunks.
*/
/*------------------------------------------------------------------------------
* Private static functions.
*/
static int rx2_close (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public functions.
*/
int
rx2_open (SF_PRIVATE *psf)
{ static const char *marker_type [4] =
{ "Original Enabled", "Enabled Hidden",
"Additional/PencilTool", "Disabled"
} ;
int error, marker, length, glob_offset, slce_count, frames ;
int sdat_length = 0, slce_total = 0 ;
int n_channels ;
/* So far only doing read. */
psf_binheader_readf (psf, "Epm4", 0, &marker, &length) ;
if (marker != CAT_MARKER)
{ psf_log_printf (psf, "length : %d\n", length) ;
return -1000 ;
} ;
if (length != psf->filelength - 8)
psf_log_printf (psf, "%M : %d (should be %d)\n", marker, length, psf->filelength - 8) ;
else
psf_log_printf (psf, "%M : %d\n", marker, length) ;
/* 'REX2' marker */
psf_binheader_readf (psf, "m", &marker) ;
psf_log_printf (psf, "%M", marker) ;
/* 'HEAD' marker */
psf_binheader_readf (psf, "m", &marker) ;
psf_log_printf (psf, "%M\n", marker) ;
/* Grab 'GLOB' offset. */
psf_binheader_readf (psf, "E4", &glob_offset) ;
glob_offset += 0x14 ; /* Add the current file offset. */
/* Jump to offset 0x30 */
psf_binheader_readf (psf, "p", 0x30) ;
/* Get name length */
length = 0 ;
psf_binheader_readf (psf, "1", &length) ;
if (length >= SIGNED_SIZEOF (psf->u.cbuf))
{ psf_log_printf (psf, " Text : %d *** Error : Too sf_count_t!\n") ;
return -1001 ;
}
memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
psf_binheader_readf (psf, "b", psf->u.cbuf, length) ;
psf_log_printf (psf, " Text : \"%s\"\n", psf->u.cbuf) ;
/* Jump to GLOB offset position. */
if (glob_offset & 1)
glob_offset ++ ;
psf_binheader_readf (psf, "p", glob_offset) ;
slce_count = 0 ;
/* GLOB */
while (1)
{ psf_binheader_readf (psf, "m", &marker) ;
if (marker != SLCE_MARKER && slce_count > 0)
{ psf_log_printf (psf, " SLCE count : %d\n", slce_count) ;
slce_count = 0 ;
}
switch (marker)
{ case GLOB_MARKER:
psf_binheader_readf (psf, "E4", &length) ;
psf_log_printf (psf, " %M : %d\n", marker, length) ;
psf_binheader_readf (psf, "j", length) ;
break ;
case RECY_MARKER:
psf_binheader_readf (psf, "E4", &length) ;
psf_log_printf (psf, " %M : %d\n", marker, length) ;
psf_binheader_readf (psf, "j", (length+1) & 0xFFFFFFFE) ; /* ?????? */
break ;
case CAT_MARKER:
psf_binheader_readf (psf, "E4", &length) ;
psf_log_printf (psf, " %M : %d\n", marker, length) ;
/*-psf_binheader_readf (psf, "j", length) ;-*/
break ;
case DEVL_MARKER:
psf_binheader_readf (psf, "mE4", &marker, &length) ;
psf_log_printf (psf, " DEVL%M : %d\n", marker, length) ;
if (length & 1)
length ++ ;
psf_binheader_readf (psf, "j", length) ;
break ;
case EQ_MARKER:
case COMP_MARKER:
psf_binheader_readf (psf, "E4", &length) ;
psf_log_printf (psf, " %M : %d\n", marker, length) ;
/* This is weird!!!! why make this (length - 1) */
if (length & 1)
length ++ ;
psf_binheader_readf (psf, "j", length) ;
break ;
case SLCL_MARKER:
psf_log_printf (psf, " %M\n (Offset, Next Offset, Type)\n", marker) ;
slce_count = 0 ;
break ;
case SLCE_MARKER:
{ int len [4], indx ;
psf_binheader_readf (psf, "E4444", &len [0], &len [1], &len [2], &len [3]) ;
indx = ((len [3] & 0x0000FFFF) >> 8) & 3 ;
if (len [2] == 1)
{ if (indx != 1)
indx = 3 ; /* 2 cases, where next slice offset = 1 -> disabled & enabled/hidden */
psf_log_printf (psf, " %M : (%6d, ?: 0x%X, %s)\n", marker, len [1], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ;
}
else
{ slce_total += len [2] ;
psf_log_printf (psf, " %M : (%6d, SLCE_next_ofs:%d, ?: 0x%X, %s)\n", marker, len [1], len [2], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ;
} ;
slce_count ++ ;
} ;
break ;
case SINF_MARKER:
psf_binheader_readf (psf, "E4", &length) ;
psf_log_printf (psf, " %M : %d\n", marker, length) ;
psf_binheader_readf (psf, "E2", &n_channels) ;
n_channels = (n_channels & 0x0000FF00) >> 8 ;
psf_log_printf (psf, " Channels : %d\n", n_channels) ;
psf_binheader_readf (psf, "E44", &psf->sf.samplerate, &frames) ;
psf->sf.frames = frames ;
psf_log_printf (psf, " Sample Rate : %d\n", psf->sf.samplerate) ;
psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
psf_binheader_readf (psf, "E4", &length) ;
psf_log_printf (psf, " ??????????? : %d\n", length) ;
psf_binheader_readf (psf, "E4", &length) ;
psf_log_printf (psf, " ??????????? : %d\n", length) ;
break ;
case SDAT_MARKER:
psf_binheader_readf (psf, "E4", &length) ;
sdat_length = length ;
/* Get the current offset. */
psf->dataoffset = psf_binheader_readf (psf, NULL) ;
if (psf->dataoffset + length != psf->filelength)
psf_log_printf (psf, " %M : %d (should be %d)\n", marker, length, psf->dataoffset + psf->filelength) ;
else
psf_log_printf (psf, " %M : %d\n", marker, length) ;
break ;
default :
psf_log_printf (psf, "Unknown marker : 0x%X %M", marker, marker) ;
return -1003 ;
break ;
} ;
/* SDAT always last marker in file. */
if (marker == SDAT_MARKER)
break ;
} ;
puts (psf->logbuffer) ;
puts ("-----------------------------------") ;
printf ("SDAT length : %d\n", sdat_length) ;
printf ("SLCE count : %d\n", slce_count) ;
/* Hack for zero slice count. */
if (slce_count == 0 && slce_total == 1)
slce_total = frames ;
printf ("SLCE samples : %d\n", slce_total) ;
/* Two bytes per sample. */
printf ("Comp Ratio : %f:1\n", (2.0 * slce_total * n_channels) / sdat_length) ;
puts (" ") ;
psf->logbuffer [0] = 0 ;
/* OK, have the header although not too sure what it all means. */
psf->endian = SF_ENDIAN_BIG ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf_fseek (psf, psf->dataoffset, SEEK_SET))
return SFE_BAD_SEEK ;
psf->sf.format = (SF_FORMAT_REX2 | SF_FORMAT_DWVW_12) ;
psf->sf.channels = 1 ;
psf->bytewidth = 2 ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
if ((error = dwvw_init (psf, 16)))
return error ;
psf->container_close = rx2_close ;
if (! psf->sf.frames && psf->blockwidth)
psf->sf.frames = psf->datalength / psf->blockwidth ;
/* All done. */
return 0 ;
} /* rx2_open */
/*------------------------------------------------------------------------------
*/
static int
rx2_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE)
{ /* Now we know for certain the length of the file we can re-write
** correct values for the FORM, 8SVX and BODY chunks.
*/
} ;
return 0 ;
} /* rx2_close */
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 7366e813-9fee-4d1f-881e-e4a691469370
*/

613
libs/libsndfile/src/sd2.c Normal file
View File

@@ -0,0 +1,613 @@
/*
** Copyright (C) 2001-2006 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2004 Paavo Jumppanen
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** The sd2 support implemented in this file was partially sponsored
** (financially) by Paavo Jumppanen.
*/
/*
** Documentation on the Mac resource fork was obtained here :
** http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*------------------------------------------------------------------------------
* Markers.
*/
#define Sd2f_MARKER MAKE_MARKER ('S', 'd', '2', 'f')
#define Sd2a_MARKER MAKE_MARKER ('S', 'd', '2', 'a')
#define ALCH_MARKER MAKE_MARKER ('A', 'L', 'C', 'H')
#define lsf1_MARKER MAKE_MARKER ('l', 's', 'f', '1')
#define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ')
#define sdML_MARKER MAKE_MARKER ('s', 'd', 'M', 'L')
enum
{ RSRC_STR = 111,
RSRC_BIN
} ;
typedef struct
{ unsigned char * rsrc_data ;
int rsrc_len ;
int data_offset, data_length ;
int map_offset, map_length ;
int type_count, type_offset ;
int item_offset ;
int str_index, str_count ;
int string_offset ;
/* All the above just to get these three. */
int sample_size, sample_rate, channels ;
} SD2_RSRC ;
typedef struct
{ int type ;
int id ;
char name [32] ;
char value [32] ;
int value_len ;
} STR_RSRC ;
/*------------------------------------------------------------------------------
* Private static functions.
*/
static int sd2_close (SF_PRIVATE *psf) ;
static int sd2_parse_rsrc_fork (SF_PRIVATE *psf) ;
static int parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) ;
static int sd2_write_rsrc_fork (SF_PRIVATE *psf, int calc_length) ;
/*------------------------------------------------------------------------------
** Public functions.
*/
int
sd2_open (SF_PRIVATE *psf)
{ int subformat, error = 0, valid ;
/* SD2 is always big endian. */
psf->endian = SF_ENDIAN_BIG ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->rsrclength > 0))
{ psf_use_rsrc (psf, SF_TRUE) ;
valid = psf_file_valid (psf) ;
psf_use_rsrc (psf, SF_FALSE) ;
if (! valid)
{ psf_log_printf (psf, "sd2_open : psf->rsrcdes < 0\n") ;
return SFE_SD2_BAD_RSRC ;
} ;
error = sd2_parse_rsrc_fork (psf) ;
if (error)
goto error_cleanup ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SD2)
{ error = SFE_BAD_OPEN_FORMAT ;
goto error_cleanup ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
psf->dataoffset = 0 ;
/* Only open and write the resource in RDWR mode is its current length is zero. */
if (psf->mode == SFM_WRITE || (psf->mode == SFM_RDWR && psf->rsrclength == 0))
{ psf_open_rsrc (psf, psf->mode) ;
error = sd2_write_rsrc_fork (psf, SF_FALSE) ;
if (error)
goto error_cleanup ;
/* Not needed. */
psf->write_header = NULL ;
} ;
psf->container_close = sd2_close ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
switch (subformat)
{ case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */
error = pcm_init (psf) ;
break ;
default :
error = SFE_UNIMPLEMENTED ;
break ;
} ;
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
error_cleanup:
/* Close the resource fork regardless. We won't need it again. */
psf_close_rsrc (psf) ;
return error ;
} /* sd2_open */
/*------------------------------------------------------------------------------
*/
static int
sd2_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE)
{ /* Now we know for certain the audio_length of the file we can re-write
** correct values for the FORM, 8SVX and BODY chunks.
*/
} ;
return 0 ;
} /* sd2_close */
/*------------------------------------------------------------------------------
*/
static inline void
write_char (unsigned char * data, int offset, char value)
{ data [offset] = value ;
} /* write_char */
static inline void
write_short (unsigned char * data, int offset, short value)
{ data [offset] = value >> 8 ;
data [offset + 1] = value ;
} /* write_char */
static inline void
write_int (unsigned char * data, int offset, int value)
{ data [offset] = value >> 24 ;
data [offset + 1] = value >> 16 ;
data [offset + 2] = value >> 8 ;
data [offset + 3] = value ;
} /* write_int */
static inline void
write_marker (unsigned char * data, int offset, int value)
{
if (CPU_IS_BIG_ENDIAN)
{ data [offset] = value >> 24 ;
data [offset + 1] = value >> 16 ;
data [offset + 2] = value >> 8 ;
data [offset + 3] = value ;
}
else
{ data [offset] = value ;
data [offset + 1] = value >> 8 ;
data [offset + 2] = value >> 16 ;
data [offset + 3] = value >> 24 ;
} ;
} /* write_marker */
static void
write_str (unsigned char * data, int offset, char * buffer, int buffer_len)
{ memcpy (data + offset, buffer, buffer_len) ;
} /* write_str */
static int
sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length))
{ SD2_RSRC rsrc ;
STR_RSRC str_rsrc [] =
{ { RSRC_STR, 1000, "_sample-size", "", 0 },
{ RSRC_STR, 1001, "_sample-rate", "", 0 },
{ RSRC_STR, 1002, "_channels", "", 0 },
{ RSRC_BIN, 1000, "_Markers", "", 8 }
} ;
int k, str_offset, data_offset, next_str ;
psf_use_rsrc (psf, SF_TRUE) ;
memset (&rsrc, 0, sizeof (rsrc)) ;
rsrc.sample_rate = psf->sf.samplerate ;
rsrc.sample_size = psf->bytewidth ;
rsrc.channels = psf->sf.channels ;
rsrc.rsrc_data = psf->header ;
rsrc.rsrc_len = sizeof (psf->header) ;
memset (rsrc.rsrc_data, 0xea, rsrc.rsrc_len) ;
LSF_SNPRINTF (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size) ;
LSF_SNPRINTF (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate) ;
LSF_SNPRINTF (str_rsrc [2].value, sizeof (str_rsrc [2].value), "_%d", rsrc.channels) ;
for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
{ if (str_rsrc [k].value_len == 0)
{ str_rsrc [k].value_len = strlen (str_rsrc [k].value) ;
str_rsrc [k].value [0] = str_rsrc [k].value_len - 1 ;
} ;
/* Turn name string into a pascal string. */
str_rsrc [k].name [0] = strlen (str_rsrc [k].name) - 1 ;
} ;
rsrc.data_offset = 0x100 ;
/*
** Calculate data length :
** length of strings, plus the length of the sdML chunk.
*/
rsrc.data_length = 0 ;
for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
rsrc.data_length += str_rsrc [k].value_len + 4 ;
rsrc.map_offset = rsrc.data_offset + rsrc.data_length ;
/* Very start of resource fork. */
write_int (rsrc.rsrc_data, 0, rsrc.data_offset) ;
write_int (rsrc.rsrc_data, 4, rsrc.map_offset) ;
write_int (rsrc.rsrc_data, 8, rsrc.data_length) ;
write_char (rsrc.rsrc_data, 0x30, strlen (psf->filename)) ;
write_str (rsrc.rsrc_data, 0x31, psf->filename, strlen (psf->filename)) ;
write_short (rsrc.rsrc_data, 0x50, 0) ;
write_marker (rsrc.rsrc_data, 0x52, Sd2f_MARKER) ;
write_marker (rsrc.rsrc_data, 0x56, lsf1_MARKER) ;
/* Very start of resource map. */
write_int (rsrc.rsrc_data, rsrc.map_offset + 0, rsrc.data_offset) ;
write_int (rsrc.rsrc_data, rsrc.map_offset + 4, rsrc.map_offset) ;
write_int (rsrc.rsrc_data, rsrc.map_offset + 8, rsrc.data_length) ;
/* These I don't currently understand. */
if (1)
{ write_char (rsrc.rsrc_data, rsrc.map_offset+ 16, 1) ;
/* Next resource map. */
write_int (rsrc.rsrc_data, rsrc.map_offset + 17, 0x12345678) ;
/* File ref number. */
write_short (rsrc.rsrc_data, rsrc.map_offset + 21, 0xabcd) ;
/* Fork attributes. */
write_short (rsrc.rsrc_data, rsrc.map_offset + 23, 0) ;
} ;
/* Resource type offset. */
rsrc.type_offset = rsrc.map_offset + 30 ;
write_short (rsrc.rsrc_data, rsrc.map_offset + 24, rsrc.type_offset - rsrc.map_offset - 2) ;
/* Type index max. */
rsrc.type_count = 2 ;
write_short (rsrc.rsrc_data, rsrc.map_offset + 28, rsrc.type_count - 1) ;
rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
rsrc.str_count = ARRAY_LEN (str_rsrc) ;
rsrc.string_offset = rsrc.item_offset + (rsrc.str_count + 1) * 12 - rsrc.map_offset ;
write_short (rsrc.rsrc_data, rsrc.map_offset + 26, rsrc.string_offset) ;
/* Write 'STR ' resource type. */
rsrc.str_count = 3 ;
write_marker (rsrc.rsrc_data, rsrc.type_offset, STR_MARKER) ;
write_short (rsrc.rsrc_data, rsrc.type_offset + 4, rsrc.str_count - 1) ;
write_short (rsrc.rsrc_data, rsrc.type_offset + 6, 0x12) ;
/* Write 'sdML' resource type. */
write_marker (rsrc.rsrc_data, rsrc.type_offset + 8, sdML_MARKER) ;
write_short (rsrc.rsrc_data, rsrc.type_offset + 12, 0) ;
write_short (rsrc.rsrc_data, rsrc.type_offset + 14, 0x36) ;
str_offset = rsrc.map_offset + rsrc.string_offset ;
next_str = 0 ;
data_offset = rsrc.data_offset ;
for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
{ write_str (rsrc.rsrc_data, str_offset, str_rsrc [k].name, strlen (str_rsrc [k].name)) ;
write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12, str_rsrc [k].id) ;
write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 2, next_str) ;
str_offset += strlen (str_rsrc [k].name) ;
next_str += strlen (str_rsrc [k].name) ;
write_int (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 4, data_offset - rsrc.data_offset) ;
write_int (rsrc.rsrc_data, data_offset, str_rsrc [k].value_len) ;
write_str (rsrc.rsrc_data, data_offset + 4, str_rsrc [k].value, str_rsrc [k].value_len) ;
data_offset += 4 + str_rsrc [k].value_len ;
} ;
/* Finally, calculate and set map length. */
rsrc.map_length = str_offset - rsrc.map_offset ;
write_int (rsrc.rsrc_data, 12, rsrc.map_length) ;
write_int (rsrc.rsrc_data, rsrc.map_offset + 12, rsrc.map_length) ;
rsrc.rsrc_len = rsrc.map_offset + rsrc.map_length ;
psf_fwrite (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ;
psf_use_rsrc (psf, SF_FALSE) ;
if (psf->error)
return psf->error ;
return 0 ;
} /* sd2_write_rsrc_fork */
/*------------------------------------------------------------------------------
*/
static inline int
read_char (const unsigned char * data, int offset)
{ return data [offset] ;
} /* read_char */
static inline int
read_short (const unsigned char * data, int offset)
{ return (data [offset] << 8) + data [offset + 1] ;
} /* read_short */
static inline int
read_int (const unsigned char * data, int offset)
{ return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
} /* read_int */
static inline int
read_marker (const unsigned char * data, int offset)
{
if (CPU_IS_BIG_ENDIAN)
return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
else if (CPU_IS_LITTLE_ENDIAN)
return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (data [offset + 3] << 24) ;
else
return 0x666 ;
} /* read_marker */
static void
read_str (const unsigned char * data, int offset, char * buffer, int buffer_len)
{ int k ;
memset (buffer, 0, buffer_len) ;
for (k = 0 ; k < buffer_len - 1 ; k++)
{ if (isprint (data [offset + k]) == 0)
return ;
buffer [k] = data [offset + k] ;
} ;
return ;
} /* read_str */
static int
sd2_parse_rsrc_fork (SF_PRIVATE *psf)
{ SD2_RSRC rsrc ;
int k, marker, error = 0 ;
psf_use_rsrc (psf, SF_TRUE) ;
memset (&rsrc, 0, sizeof (rsrc)) ;
rsrc.rsrc_len = psf_get_filelen (psf) ;
psf_log_printf (psf, "Resource length : %d (0x%04X)\n", rsrc.rsrc_len, rsrc.rsrc_len) ;
if (rsrc.rsrc_len > SIGNED_SIZEOF (psf->header))
rsrc.rsrc_data = calloc (1, rsrc.rsrc_len) ;
else
rsrc.rsrc_data = psf->header ;
/* Read in the whole lot. */
psf_fread (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ;
/* Reset the header storage because we have changed to the rsrcdes. */
psf->headindex = psf->headend = rsrc.rsrc_len ;
rsrc.data_offset = read_int (rsrc.rsrc_data, 0) ;
rsrc.map_offset = read_int (rsrc.rsrc_data, 4) ;
rsrc.data_length = read_int (rsrc.rsrc_data, 8) ;
rsrc.map_length = read_int (rsrc.rsrc_data, 12) ;
if (rsrc.data_offset == 0x51607 && rsrc.map_offset == 0x20000)
{ psf_log_printf (psf, "Trying offset of 0x52 bytes.\n") ;
rsrc.data_offset = read_int (rsrc.rsrc_data, 0x52 + 0) + 0x52 ;
rsrc.map_offset = read_int (rsrc.rsrc_data, 0x52 + 4) + 0x52 ;
rsrc.data_length = read_int (rsrc.rsrc_data, 0x52 + 8) ;
rsrc.map_length = read_int (rsrc.rsrc_data, 0x52 + 12) ;
} ;
psf_log_printf (psf, " data offset : 0x%04X\n map offset : 0x%04X\n"
" data length : 0x%04X\n map length : 0x%04X\n",
rsrc.data_offset, rsrc.map_offset, rsrc.data_length, rsrc.map_length) ;
if (rsrc.data_offset > rsrc.rsrc_len)
{ psf_log_printf (psf, "Error : rsrc.data_offset (%d, 0x%x) > len\n", rsrc.data_offset, rsrc.data_offset) ;
error = SFE_SD2_BAD_DATA_OFFSET ;
goto parse_rsrc_fork_cleanup ;
} ;
if (rsrc.map_offset > rsrc.rsrc_len)
{ psf_log_printf (psf, "Error : rsrc.map_offset > len\n") ;
error = SFE_SD2_BAD_MAP_OFFSET ;
goto parse_rsrc_fork_cleanup ;
} ;
if (rsrc.data_length > rsrc.rsrc_len)
{ psf_log_printf (psf, "Error : rsrc.data_length > len\n") ;
error = SFE_SD2_BAD_DATA_LENGTH ;
goto parse_rsrc_fork_cleanup ;
} ;
if (rsrc.map_length > rsrc.rsrc_len)
{ psf_log_printf (psf, "Error : rsrc.map_length > len\n") ;
error = SFE_SD2_BAD_MAP_LENGTH ;
goto parse_rsrc_fork_cleanup ;
} ;
if (rsrc.data_offset + rsrc.data_length != rsrc.map_offset || rsrc.map_offset + rsrc.map_length != rsrc.rsrc_len)
{ psf_log_printf (psf, "Error : This does not look like a MacOSX resource fork.\n") ;
error = SFE_SD2_BAD_RSRC ;
goto parse_rsrc_fork_cleanup ;
} ;
rsrc.string_offset = rsrc.map_offset + read_short (rsrc.rsrc_data, rsrc.map_offset + 26) ;
if (rsrc.string_offset > rsrc.rsrc_len)
{ psf_log_printf (psf, "Bad string offset (%d).\n", rsrc.string_offset) ;
error = SFE_SD2_BAD_RSRC ;
goto parse_rsrc_fork_cleanup ;
} ;
rsrc.type_offset = rsrc.map_offset + 30 ;
rsrc.type_count = read_short (rsrc.rsrc_data, rsrc.map_offset + 28) + 1 ;
if (rsrc.type_count < 1)
{ psf_log_printf (psf, "Bad type count.\n") ;
error = SFE_SD2_BAD_RSRC ;
goto parse_rsrc_fork_cleanup ;
} ;
rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
if (rsrc.item_offset < 0 || rsrc.item_offset > rsrc.rsrc_len)
{ psf_log_printf (psf, "Bad item offset (%d).\n", rsrc.item_offset) ;
error = SFE_SD2_BAD_RSRC ;
goto parse_rsrc_fork_cleanup ;
} ;
rsrc.str_index = -1 ;
for (k = 0 ; k < rsrc.type_count ; k ++)
{ marker = read_marker (rsrc.rsrc_data, rsrc.type_offset + k * 8) ;
if (marker == STR_MARKER)
{ rsrc.str_index = k ;
rsrc.str_count = read_short (rsrc.rsrc_data, rsrc.type_offset + k * 8 + 4) + 1 ;
error = parse_str_rsrc (psf, &rsrc) ;
goto parse_rsrc_fork_cleanup ;
} ;
} ;
psf_log_printf (psf, "No 'STR ' resource.\n") ;
error = SFE_SD2_BAD_RSRC ;
parse_rsrc_fork_cleanup :
psf_use_rsrc (psf, SF_FALSE) ;
if ((void *) rsrc.rsrc_data < (void *) psf || (void *) rsrc.rsrc_data > (void *) (psf + 1))
free (rsrc.rsrc_data) ;
return error ;
} /* sd2_parse_rsrc_fork */
static int
parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
{ char name [32], value [32] ;
int k, str_offset, data_offset, data_len, rsrc_id ;
psf_log_printf (psf, "Finding parameters :\n") ;
str_offset = rsrc->string_offset ;
for (k = 0 ; k < rsrc->str_count ; k++)
{ int slen ;
slen = read_char (rsrc->rsrc_data, str_offset) ;
read_str (rsrc->rsrc_data, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ;
str_offset += slen + 1 ;
rsrc_id = read_short (rsrc->rsrc_data, rsrc->item_offset + k * 12) ;
data_offset = rsrc->data_offset + read_int (rsrc->rsrc_data, rsrc->item_offset + k * 12 + 4) ;
if (data_offset < 0 || data_offset > rsrc->rsrc_len)
{ psf_log_printf (psf, "Bad data offset (%d)\n", data_offset) ;
return SFE_SD2_BAD_DATA_OFFSET ;
} ;
data_len = read_int (rsrc->rsrc_data, data_offset) ;
if (data_len < 0 || data_len > rsrc->rsrc_len)
{ psf_log_printf (psf, "Bad data length (%d).\n", data_len) ;
return SFE_SD2_BAD_RSRC ;
} ;
slen = read_char (rsrc->rsrc_data, data_offset + 4) ;
read_str (rsrc->rsrc_data, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)) ;
psf_log_printf (psf, " %-12s 0x%04x %4d %2d %2d '%s'\n", name, data_offset, rsrc_id, data_len, slen, value) ;
if (strcmp (name, "sample-size") == 0 && rsrc->sample_size == 0)
rsrc->sample_size = strtol (value, NULL, 10) ;
else if (strcmp (name, "sample-rate") == 0 && rsrc->sample_rate == 0)
rsrc->sample_rate = strtol (value, NULL, 10) ;
else if (strcmp (name, "channels") == 0 && rsrc->channels == 0)
rsrc->channels = strtol (value, NULL, 10) ;
} ;
if (rsrc->sample_rate < 0)
{ psf_log_printf (psf, "Bad sample rate (%d)\n", rsrc->sample_rate) ;
return SFE_SD2_BAD_RSRC ;
} ;
if (rsrc->channels < 0)
{ psf_log_printf (psf, "Bad channel count (%d)\n", rsrc->channels) ;
return SFE_SD2_BAD_RSRC ;
} ;
psf->sf.samplerate = rsrc->sample_rate ;
psf->sf.channels = rsrc->channels ;
psf->bytewidth = rsrc->sample_size ;
switch (rsrc->sample_size)
{ case 1 :
psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_S8 ;
break ;
case 2 :
psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ;
break ;
case 3 :
psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_24 ;
break ;
default :
psf_log_printf (psf, "Bad sample size (%d)\n", rsrc->sample_size) ;
return SFE_SD2_BAD_SAMPLE_SIZE ;
} ;
psf_log_printf (psf, "ok\n") ;
return 0 ;
} /* parse_str_rsrc */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 1ee183e5-6b9f-4c2c-bd0a-24f35595cefc
*/

993
libs/libsndfile/src/sds.c Normal file
View File

@@ -0,0 +1,993 @@
/*
** Copyright (C) 2002-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#include "float_cast.h"
/*------------------------------------------------------------------------------
*/
#define SDS_DATA_OFFSET 0x15
#define SDS_BLOCK_SIZE 127
#define SDS_AUDIO_BYTES_PER_BLOCK 120
#define SDS_3BYTE_TO_INT_DECODE(x) (((x) & 0x7F) | (((x) & 0x7F00) >> 1) | (((x) & 0x7F0000) >> 2))
#define SDS_INT_TO_3BYTE_ENCODE(x) (((x) & 0x7F) | (((x) << 1) & 0x7F00) | (((x) << 2) & 0x7F0000))
/*------------------------------------------------------------------------------
** Typedefs.
*/
typedef struct tag_SDS_PRIVATE
{ int bitwidth, frames ;
int samplesperblock, total_blocks ;
int (*reader) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ;
int (*writer) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ;
int read_block, read_count ;
unsigned char read_data [SDS_BLOCK_SIZE] ;
int read_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */
int write_block, write_count ;
unsigned char write_data [SDS_BLOCK_SIZE] ;
int write_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */
} SDS_PRIVATE ;
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int sds_close (SF_PRIVATE *psf) ;
static int sds_write_header (SF_PRIVATE *psf, int calc_length) ;
static int sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static sf_count_t sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t sds_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static sf_count_t sds_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int readcount) ;
static int sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, const int *iptr, int writecount) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
sds_open (SF_PRIVATE *psf)
{ SDS_PRIVATE *psds ;
int error = 0 ;
/* Hmmmm, need this here to pass update_header_test. */
psf->sf.frames = 0 ;
if (! (psds = calloc (1, sizeof (SDS_PRIVATE))))
return SFE_MALLOC_FAILED ;
psf->fdata = psds ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = sds_read_header (psf, psds)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SDS)
return SFE_BAD_OPEN_FORMAT ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (sds_write_header (psf, SF_FALSE))
return psf->error ;
psf->write_header = sds_write_header ;
psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ;
} ;
if ((error = sds_init (psf, psds)) != 0)
return error ;
psf->seek = sds_seek ;
psf->container_close = sds_close ;
psf->blockwidth = 0 ;
return error ;
} /* sds_open */
/*------------------------------------------------------------------------------
*/
static int
sds_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ SDS_PRIVATE *psds ;
if ((psds = (SDS_PRIVATE *) psf->fdata) == NULL)
{ psf_log_printf (psf, "*** Bad psf->fdata ptr.\n") ;
return SFE_INTERNAL ;
} ;
if (psds->write_count > 0)
{ memset (&(psds->write_data [psds->write_count]), 0, (psds->samplesperblock - psds->write_count) * sizeof (int)) ;
psds->writer (psf, psds) ;
} ;
sds_write_header (psf, SF_TRUE) ;
} ;
return 0 ;
} /* sds_close */
static int
sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{
if (psds->bitwidth < 8 || psds->bitwidth > 28)
return (psf->error = SFE_SDS_BAD_BIT_WIDTH) ;
if (psds->bitwidth < 14)
{ psds->reader = sds_2byte_read ;
psds->writer = sds_2byte_write ;
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 2 ;
}
else if (psds->bitwidth < 21)
{ psds->reader = sds_3byte_read ;
psds->writer = sds_3byte_write ;
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 3 ;
}
else
{ psds->reader = sds_4byte_read ;
psds->writer = sds_4byte_write ;
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 4 ;
} ;
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
{ psf->read_short = sds_read_s ;
psf->read_int = sds_read_i ;
psf->read_float = sds_read_f ;
psf->read_double = sds_read_d ;
/* Read first block. */
psds->reader (psf, psds) ;
} ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->write_short = sds_write_s ;
psf->write_int = sds_write_i ;
psf->write_float = sds_write_f ;
psf->write_double = sds_write_d ;
} ;
return 0 ;
} /* sds_init */
static int
sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char channel, bitwidth, loop_type, byte ;
unsigned short sample_no, marker ;
unsigned int samp_period, data_length, sustain_loop_start, sustain_loop_end ;
int bytesread, blockcount ;
/* Set position to start of file to begin reading header. */
bytesread = psf_binheader_readf (psf, "pE211", 0, &marker, &channel, &byte) ;
if (marker != 0xF07E || byte != 0x01)
return SFE_SDS_NOT_SDS ;
psf_log_printf (psf, "Midi Sample Dump Standard (.sds)\nF07E\n Midi Channel : %d\n", channel) ;
bytesread += psf_binheader_readf (psf, "e213", &sample_no, &bitwidth, &samp_period) ;
sample_no = SDS_3BYTE_TO_INT_DECODE (sample_no) ;
samp_period = SDS_3BYTE_TO_INT_DECODE (samp_period) ;
psds->bitwidth = bitwidth ;
psf->sf.samplerate = 1000000000 / samp_period ;
psf_log_printf (psf, " Sample Number : %d\n"
" Bit Width : %d\n"
" Sample Rate : %d\n",
sample_no, psds->bitwidth, psf->sf.samplerate) ;
bytesread += psf_binheader_readf (psf, "e3331", &data_length, &sustain_loop_start, &sustain_loop_end, &loop_type) ;
data_length = SDS_3BYTE_TO_INT_DECODE (data_length) ;
sustain_loop_start = SDS_3BYTE_TO_INT_DECODE (sustain_loop_start) ;
sustain_loop_end = SDS_3BYTE_TO_INT_DECODE (sustain_loop_end) ;
psf_log_printf (psf, " Sustain Loop\n"
" Start : %d\n"
" End : %d\n"
" Loop Type : %d\n",
sustain_loop_start, sustain_loop_end, loop_type) ;
psf->dataoffset = SDS_DATA_OFFSET ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (data_length != psf->filelength - psf->dataoffset)
{ psf_log_printf (psf, " Datalength : %d (truncated data??? %d)\n", data_length, psf->filelength - psf->dataoffset) ;
data_length = psf->filelength - psf->dataoffset ;
}
else
psf_log_printf (psf, " Datalength : %d\n", data_length) ;
bytesread += psf_binheader_readf (psf, "1", &byte) ;
if (byte != 0xF7)
psf_log_printf (psf, "bad end : %X\n", byte & 0xFF) ;
for (blockcount = 0 ; bytesread < psf->filelength ; blockcount++)
{
bytesread += psf_fread (&marker, 1, 2, psf) ;
if (marker == 0)
break ;
psf_fseek (psf, SDS_BLOCK_SIZE - 2, SEEK_CUR) ;
bytesread += SDS_BLOCK_SIZE - 2 ;
} ;
psf_log_printf (psf, "\nBlocks : %d\n", blockcount) ;
psds->total_blocks = blockcount ;
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / ((psds->bitwidth + 6) / 7) ;
psf_log_printf (psf, "Samples/Block : %d\n", psds->samplesperblock) ;
psf_log_printf (psf, "Frames : %d\n", blockcount * psds->samplesperblock) ;
psf->sf.frames = blockcount * psds->samplesperblock ;
psds->frames = blockcount * psds->samplesperblock ;
/* Always Mono */
psf->sf.channels = 1 ;
psf->sf.sections = 1 ;
/*
** Lie to the user about PCM bit width. Always round up to
** the next multiple of 8.
*/
switch ((psds->bitwidth + 7) / 8)
{ case 1 :
psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_S8 ;
break ;
case 2 :
psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_16 ;
break ;
case 3 :
psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_24 ;
break ;
case 4 :
psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_32 ;
break ;
default :
psf_log_printf (psf, "*** Weird byte width (%d)\n", (psds->bitwidth + 7) / 8) ;
return SFE_SDS_BAD_BIT_WIDTH ;
} ;
psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ;
return 0 ;
} /* sds_read_header */
static int
sds_write_header (SF_PRIVATE *psf, int calc_length)
{ SDS_PRIVATE *psds ;
sf_count_t current ;
int samp_period, data_length, sustain_loop_start, sustain_loop_end ;
unsigned char loop_type = 0 ;
if ((psds = (SDS_PRIVATE *) psf->fdata) == NULL)
{ psf_log_printf (psf, "*** Bad psf->fdata ptr.\n") ;
return SFE_INTERNAL ;
} ;
if (psf->pipeoffset > 0)
return 0 ;
current = psf_ftell (psf) ;
if (calc_length)
psf->sf.frames = psds->total_blocks * psds->samplesperblock + psds->write_count ;
if (psds->write_count > 0)
{ int current_count = psds->write_count ;
int current_block = psds->write_block ;
psds->writer (psf, psds) ;
psf_fseek (psf, -1 * SDS_BLOCK_SIZE, SEEK_CUR) ;
psds->write_count = current_count ;
psds->write_block = current_block ;
} ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
if (psf->is_pipe == SF_FALSE)
psf_fseek (psf, 0, SEEK_SET) ;
psf_binheader_writef (psf, "E211", 0xF07E, 0, 1) ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
psds->bitwidth = 8 ;
break ;
case SF_FORMAT_PCM_16 :
psds->bitwidth = 16 ;
break ;
case SF_FORMAT_PCM_24 :
psds->bitwidth = 24 ;
break ;
default:
return SFE_SDS_BAD_BIT_WIDTH ;
} ;
samp_period = SDS_INT_TO_3BYTE_ENCODE (1000000000 / psf->sf.samplerate) ;
psf_binheader_writef (psf, "e213", 0, psds->bitwidth, samp_period) ;
data_length = SDS_INT_TO_3BYTE_ENCODE (psds->total_blocks * SDS_BLOCK_SIZE) ;
sustain_loop_start = SDS_INT_TO_3BYTE_ENCODE (0) ;
sustain_loop_end = SDS_INT_TO_3BYTE_ENCODE (psf->sf.frames) ;
psf_binheader_writef (psf, "e33311", data_length, sustain_loop_start, sustain_loop_end, loop_type, 0xF7) ;
/* Header construction complete so write it out. */
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
psf->datalength = psds->write_block * SDS_BLOCK_SIZE ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* sds_write_header */
/*------------------------------------------------------------------------------
*/
static int
sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->read_block ++ ;
psds->read_count = 0 ;
if (psds->read_block * psds->samplesperblock > psds->frames)
{ memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
return 1 ;
} ;
if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
if (psds->read_data [0] != 0xF0)
{ printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
} ;
checksum = psds->read_data [1] ;
if (checksum != 0x7E)
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
}
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->read_data [k] ;
checksum &= 0x7F ;
if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
{ psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
} ;
ucptr = psds->read_data + 5 ;
for (k = 0 ; k < 120 ; k += 2)
{ sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) ;
psds->read_samples [k / 2] = (int) (sample - 0x80000000) ;
} ;
return 1 ;
} /* sds_2byte_read */
static int
sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->read_block ++ ;
psds->read_count = 0 ;
if (psds->read_block * psds->samplesperblock > psds->frames)
{ memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
return 1 ;
} ;
if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
if (psds->read_data [0] != 0xF0)
{ printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
} ;
checksum = psds->read_data [1] ;
if (checksum != 0x7E)
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
}
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->read_data [k] ;
checksum &= 0x7F ;
if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
{ psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
} ;
ucptr = psds->read_data + 5 ;
for (k = 0 ; k < 120 ; k += 3)
{ sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) ;
psds->read_samples [k / 3] = (int) (sample - 0x80000000) ;
} ;
return 1 ;
} /* sds_3byte_read */
static int
sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->read_block ++ ;
psds->read_count = 0 ;
if (psds->read_block * psds->samplesperblock > psds->frames)
{ memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
return 1 ;
} ;
if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
if (psds->read_data [0] != 0xF0)
{ printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
} ;
checksum = psds->read_data [1] ;
if (checksum != 0x7E)
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
}
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->read_data [k] ;
checksum &= 0x7F ;
if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
{ psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
} ;
ucptr = psds->read_data + 5 ;
for (k = 0 ; k < 120 ; k += 4)
{ sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) + (ucptr [k + 3] << 4) ;
psds->read_samples [k / 4] = (int) (sample - 0x80000000) ;
} ;
return 1 ;
} /* sds_4byte_read */
static sf_count_t
sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = sds_read (psf, psds, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = iptr [k] >> 16 ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* sds_read_s */
static sf_count_t
sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int total ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
total = sds_read (psf, psds, ptr, len) ;
return total ;
} /* sds_read_i */
static sf_count_t
sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
if (psf->norm_float == SF_TRUE)
normfact = 1.0 / 0x80000000 ;
else
normfact = 1.0 / (1 << psds->bitwidth) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = sds_read (psf, psds, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * iptr [k] ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* sds_read_f */
static sf_count_t
sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
if (psf->norm_double == SF_TRUE)
normfact = 1.0 / 0x80000000 ;
else
normfact = 1.0 / (1 << psds->bitwidth) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = sds_read (psf, psds, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * iptr [k] ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* sds_read_d */
static int
sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *ptr, int len)
{ int count, total = 0 ;
while (total < len)
{ if (psds->read_block * psds->samplesperblock >= psds->frames)
{ memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ;
return total ;
} ;
if (psds->read_count >= psds->samplesperblock)
psds->reader (psf, psds) ;
count = (psds->samplesperblock - psds->read_count) ;
count = (len - total > count) ? count : len - total ;
memcpy (&(ptr [total]), &(psds->read_samples [psds->read_count]), count * sizeof (int)) ;
total += count ;
psds->read_count += count ;
} ;
return total ;
} /* sds_read */
/*==============================================================================
*/
static sf_count_t
sds_seek (SF_PRIVATE *psf, int mode, sf_count_t seek_from_start)
{ SDS_PRIVATE *psds ;
sf_count_t file_offset ;
int newblock, newsample ;
if ((psds = psf->fdata) == NULL)
{ psf->error = SFE_INTERNAL ;
return PSF_SEEK_ERROR ;
} ;
if (psf->datalength < 0 || psf->dataoffset < 0)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
if (seek_from_start < 0 || seek_from_start > psf->sf.frames)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
if (mode == SFM_READ && psds->write_count > 0)
psds->writer (psf, psds) ;
newblock = seek_from_start / psds->samplesperblock ;
newsample = seek_from_start % psds->samplesperblock ;
switch (mode)
{ case SFM_READ :
if (newblock > psds->total_blocks)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ;
if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset)
{ psf->error = SFE_SEEK_FAILED ;
return PSF_SEEK_ERROR ;
} ;
psds->read_block = newblock ;
psds->reader (psf, psds) ;
psds->read_count = newsample ;
break ;
case SFM_WRITE :
if (newblock > psds->total_blocks)
{ psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
} ;
file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ;
if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset)
{ psf->error = SFE_SEEK_FAILED ;
return PSF_SEEK_ERROR ;
} ;
psds->write_block = newblock ;
psds->reader (psf, psds) ;
psds->write_count = newsample ;
break ;
default :
psf->error = SFE_BAD_SEEK ;
return PSF_SEEK_ERROR ;
break ;
} ;
return seek_from_start ;
} /* sds_seek */
/*==============================================================================
*/
static int
sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->write_data [0] = 0xF0 ;
psds->write_data [1] = 0x7E ;
psds->write_data [2] = 0 ; /* Channel number */
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
ucptr = psds->write_data + 5 ;
for (k = 0 ; k < 120 ; k += 2)
{ sample = psds->write_samples [k / 2] ;
sample += 0x80000000 ;
ucptr [k] = (sample >> 25) & 0x7F ;
ucptr [k + 1] = (sample >> 18) & 0x7F ;
} ;
checksum = psds->write_data [1] ;
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->write_data [k] ;
checksum &= 0x7F ;
psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
psds->write_block ++ ;
psds->write_count = 0 ;
if (psds->write_block > psds->total_blocks)
psds->total_blocks = psds->write_block ;
psds->frames = psds->total_blocks * psds->samplesperblock ;
return 1 ;
} /* sds_2byte_write */
static int
sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->write_data [0] = 0xF0 ;
psds->write_data [1] = 0x7E ;
psds->write_data [2] = 0 ; /* Channel number */
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
ucptr = psds->write_data + 5 ;
for (k = 0 ; k < 120 ; k += 3)
{ sample = psds->write_samples [k / 3] ;
sample += 0x80000000 ;
ucptr [k] = (sample >> 25) & 0x7F ;
ucptr [k + 1] = (sample >> 18) & 0x7F ;
ucptr [k + 2] = (sample >> 11) & 0x7F ;
} ;
checksum = psds->write_data [1] ;
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->write_data [k] ;
checksum &= 0x7F ;
psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
psds->write_block ++ ;
psds->write_count = 0 ;
if (psds->write_block > psds->total_blocks)
psds->total_blocks = psds->write_block ;
psds->frames = psds->total_blocks * psds->samplesperblock ;
return 1 ;
} /* sds_3byte_write */
static int
sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->write_data [0] = 0xF0 ;
psds->write_data [1] = 0x7E ;
psds->write_data [2] = 0 ; /* Channel number */
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
ucptr = psds->write_data + 5 ;
for (k = 0 ; k < 120 ; k += 4)
{ sample = psds->write_samples [k / 4] ;
sample += 0x80000000 ;
ucptr [k] = (sample >> 25) & 0x7F ;
ucptr [k + 1] = (sample >> 18) & 0x7F ;
ucptr [k + 2] = (sample >> 11) & 0x7F ;
ucptr [k + 3] = (sample >> 4) & 0x7F ;
} ;
checksum = psds->write_data [1] ;
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->write_data [k] ;
checksum &= 0x7F ;
psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
psds->write_block ++ ;
psds->write_count = 0 ;
if (psds->write_block > psds->total_blocks)
psds->total_blocks = psds->write_block ;
psds->frames = psds->total_blocks * psds->samplesperblock ;
return 1 ;
} /* sds_4byte_write */
static sf_count_t
sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = ptr [total + k] << 16 ;
count = sds_write (psf, psds, iptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* sds_write_s */
static sf_count_t
sds_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int total ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
total = sds_write (psf, psds, ptr, len) ;
return total ;
} /* sds_write_i */
static sf_count_t
sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
if (psf->norm_float == SF_TRUE)
normfact = 1.0 * 0x80000000 ;
else
normfact = 1.0 * (1 << psds->bitwidth) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = normfact * ptr [total + k] ;
count = sds_write (psf, psds, iptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* sds_write_f */
static sf_count_t
sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
if (psf->norm_double == SF_TRUE)
normfact = 1.0 * 0x80000000 ;
else
normfact = 1.0 * (1 << psds->bitwidth) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : len ;
for (k = 0 ; k < writecount ; k++)
iptr [k] = normfact * ptr [total + k] ;
count = sds_write (psf, psds, iptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* sds_write_d */
static int
sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, const int *ptr, int len)
{ int count, total = 0 ;
while (total < len)
{ count = psds->samplesperblock - psds->write_count ;
if (count > len - total)
count = len - total ;
memcpy (&(psds->write_samples [psds->write_count]), &(ptr [total]), count * sizeof (int)) ;
total += count ;
psds->write_count += count ;
if (psds->write_count >= psds->samplesperblock)
psds->writer (psf, psds) ;
} ;
return total ;
} /* sds_write */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: d5d26aa3-368c-4ca6-bb85-377e5a2578cc
*/

View File

@@ -0,0 +1,67 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Some defines that microsoft 'forgot' to implement. */
#ifndef S_IRWXU
#define S_IRWXU 0000700 /* rwx, owner */
#endif
#ifndef S_IRUSR
#define S_IRUSR 0000400 /* read permission, owner */
#endif
#ifndef S_IWUSR
#define S_IWUSR 0000200 /* write permission, owner */
#endif
#ifndef S_IXUSR
#define S_IXUSR 0000100 /* execute/search permission, owner */
#endif
#define S_IRWXG 0000070 /* rwx, group */
#define S_IRGRP 0000040 /* read permission, group */
#define S_IWGRP 0000020 /* write permission, grougroup */
#define S_IXGRP 0000010 /* execute/search permission, group */
#define S_IRWXO 0000007 /* rwx, other */
#define S_IROTH 0000004 /* read permission, other */
#define S_IWOTH 0000002 /* write permission, other */
#define S_IXOTH 0000001 /* execute/search permission, other */
#ifndef S_ISFIFO
#define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO)
#endif
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & _S_IFREG) == _S_IFREG)
#endif
/*
** Don't know if these are still needed.
**
** #define _IFMT _S_IFMT
** #define _IFREG _S_IFREG
*/
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 253aea6d-6299-46fd-8d06-bc5f6224c8fe
*/

View File

@@ -0,0 +1,108 @@
/*
** Copyright (C) 2005 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** Autoconf leaves many config parameters undefined.
** Here we change then from being undefined to defining them to 0.
** This allows things like:
**
** #if HAVE_CONFIG_PARAM
**
** and
**
** if (HAVE_CONFIG_PARAM)
** do_something () ;
*/
#ifndef SFCONFIG_H
#define SFCONFIG_H
/* Include the Autoconf generated file. */
#include "config.h"
/* Now fiddle the values. */
#ifndef HAVE_ALSA_ASOUNDLIB_H
#define HAVE_ALSA_ASOUNDLIB_H 0
#endif
#ifndef HAVE_BYTESWAP_H
#define HAVE_BYTESWAP_H 0
#endif
#ifndef HAVE_DECL_S_IRGRP
#define HAVE_DECL_S_IRGRP 0
#endif
#ifndef HAVE_ENDIAN_H
#define HAVE_ENDIAN_H 0
#endif
#ifndef HAVE_FSYNC
#define HAVE_FSYNC 0
#endif
#ifndef HAVE_LOCALE_H
#define HAVE_LOCALE_H 0
#endif
#ifndef HAVE_LRINT
#define HAVE_LRINT 0
#endif
#ifndef HAVE_LRINTF
#define HAVE_LRINTF 0
#endif
#ifndef HAVE_MMAP
#define HAVE_MMAP 0
#endif
#ifndef HAVE_PREAD
#define HAVE_PREAD 0
#endif
#ifndef HAVE_PWRITE
#define HAVE_PWRITE 0
#endif
#ifndef HAVE_SETLOCALE
#define HAVE_SETLOCALE 0
#endif
#ifndef HAVE_SQLITE3
#define HAVE_SQLITE3 0
#endif
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H 0
#endif
#ifndef HAVE_UNISTD_H
#define HAVE_UNISTD_H 0
#endif
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 2df2316e-8f9d-4860-bba7-f3c16c63eed3
*/

View File

@@ -0,0 +1,256 @@
/*
** Copyright (C) 1999-2006 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#if HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
/* Good, we have int64_t. */
#elif (defined (SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
typedef long long int64_t ;
#elif (defined (SIZEOF_LONG) && (SIZEOF_LONG == 8))
typedef long int64_t ;
#elif (defined (WIN32) || defined (_WIN32))
typedef __int64 int64_t ;
#else
#error "No 64 bit integer type."
#endif
#if HAVE_BYTESWAP_H
#include <byteswap.h>
#define ENDSWAP_SHORT(x) ((short) bswap_16 (x))
#define ENDSWAP_INT(x) ((int) bswap_32 (x))
#else
#define ENDSWAP_SHORT(x) ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
#define ENDSWAP_INT(x) ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
#endif
/*
** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a
** marker indicating different sections of the file.
** The following MAKE_MARKER macro allows th creation of integer constants
** for these markers.
*/
#if (CPU_IS_LITTLE_ENDIAN == 1)
#define MAKE_MARKER(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
#elif (CPU_IS_BIG_ENDIAN == 1)
#define MAKE_MARKER(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
#else
#error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
#endif
/*
** Macros to handle reading of data of a specific endian-ness into host endian
** shorts and ints. The single input is an unsigned char* pointer to the start
** of the object. There are two versions of each macro as we need to deal with
** both big and little endian CPUs.
*/
#if (CPU_IS_LITTLE_ENDIAN == 1)
#define LES2H_SHORT(x) (x)
#define LEI2H_INT(x) (x)
#define BES2H_SHORT(x) ENDSWAP_SHORT (x)
#define BEI2H_INT(x) ENDSWAP_INT (x)
#define H2BE_SHORT(x) ENDSWAP_SHORT (x)
#define H2BE_INT(x) ENDSWAP_INT (x)
#elif (CPU_IS_BIG_ENDIAN == 1)
#define LES2H_SHORT(x) ENDSWAP_SHORT (x)
#define LEI2H_INT(x) ENDSWAP_INT (x)
#define BES2H_SHORT(x) (x)
#define BEI2H_INT(x) (x)
#define H2LE_SHORT(x) ENDSWAP_SHORT (x)
#define H2LE_INT(x) ENDSWAP_INT (x)
#else
#error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
#endif
#define LET2H_SHORT_PTR(x) ((x) [1] + ((x) [2] << 8))
#define LET2H_INT_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
#define BET2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1])
#define BET2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8))
/*-----------------------------------------------------------------------------------------------
** Generic functions for performing endian swapping on integer arrays.
*/
static inline void
endswap_short_array (short *ptr, int len)
{ short temp ;
while (--len >= 0)
{ temp = ptr [len] ;
ptr [len] = ENDSWAP_SHORT (temp) ;
} ;
} /* endswap_short_array */
static inline void
endswap_short_copy (short *dest, const short *src, int len)
{
while (--len >= 0)
{ dest [len] = ENDSWAP_SHORT (src [len]) ;
} ;
} /* endswap_short_copy */
static inline void
endswap_int_array (int *ptr, int len)
{ int temp ;
while (--len >= 0)
{ temp = ptr [len] ;
ptr [len] = ENDSWAP_INT (temp) ;
} ;
} /* endswap_int_array */
static inline void
endswap_int_copy (int *dest, const int *src, int len)
{
while (--len >= 0)
{ dest [len] = ENDSWAP_INT (src [len]) ;
} ;
} /* endswap_int_copy */
/*========================================================================================
*/
#if (HAVE_BYTESWAP_H && defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
static inline void
endswap_int64_t_array (int64_t *ptr, int len)
{ int64_t value ;
while (--len >= 0)
{ value = ptr [len] ;
ptr [len] = bswap_64 (value) ;
} ;
} /* endswap_int64_t_array */
static inline void
endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
{ int64_t value ;
while (--len >= 0)
{ value = src [len] ;
dest [len] = bswap_64 (value) ;
} ;
} /* endswap_int64_t_copy */
#else
static inline void
endswap_int64_t_array (int64_t *ptr, int len)
{ unsigned char *ucptr, temp ;
ucptr = (unsigned char *) ptr ;
ucptr += 8 * len ;
while (--len >= 0)
{ ucptr -= 8 ;
temp = ucptr [0] ;
ucptr [0] = ucptr [7] ;
ucptr [7] = temp ;
temp = ucptr [1] ;
ucptr [1] = ucptr [6] ;
ucptr [6] = temp ;
temp = ucptr [2] ;
ucptr [2] = ucptr [5] ;
ucptr [5] = temp ;
temp = ucptr [3] ;
ucptr [3] = ucptr [4] ;
ucptr [4] = temp ;
} ;
} /* endswap_int64_t_array */
static inline void
endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
{ const unsigned char *psrc ;
unsigned char *pdest ;
if (dest == src)
{ endswap_int64_t_array (dest, len) ;
return ;
} ;
psrc = ((const unsigned char *) src) + 8 * len ;
pdest = ((unsigned char *) dest) + 8 * len ;
while (--len >= 0)
{ psrc -= 8 ;
pdest -= 8 ;
pdest [0] = psrc [7] ;
pdest [2] = psrc [5] ;
pdest [4] = psrc [3] ;
pdest [6] = psrc [1] ;
pdest [7] = psrc [0] ;
pdest [1] = psrc [6] ;
pdest [3] = psrc [4] ;
pdest [5] = psrc [2] ;
} ;
} /* endswap_int64_t_copy */
#endif
/* A couple of wrapper functions. */
static inline void
endswap_float_array (float *ptr, int len)
{ endswap_int_array ((void *) ptr, len) ;
} /* endswap_float_array */
static inline void
endswap_double_array (double *ptr, int len)
{ endswap_int64_t_array ((void *) ptr, len) ;
} /* endswap_double_array */
static inline void
endswap_float_copy (float *dest, const float *src, int len)
{ endswap_int_copy ((int *) dest, (const int *) src, len) ;
} /* endswap_float_copy */
static inline void
endswap_double_copy (double *dest, const double *src, int len)
{ endswap_int64_t_copy ((int64_t *) dest, (const int64_t *) src, len) ;
} /* endswap_double_copy */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f0c5cd54-42d3-4237-90ec-11fe24995de7
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,554 @@
/*
** Copyright (C) 1999-2006 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** sndfile.h -- system-wide definitions
**
** API documentation is in the doc/ directory of the source code tarball
** and at http://www.mega-nerd.com/libsndfile/api.html.
*/
#ifndef SNDFILE_H
#define SNDFILE_H
/* This is the version 1.0.X header file. */
#define SNDFILE_1
#include <stdio.h>
/* For the Metrowerks CodeWarrior Pro Compiler (mainly MacOS) */
#if (defined (__MWERKS__))
#include <unix.h>
#else
#include <sys/types.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* The following file types can be read and written.
** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise
** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and
** SF_FORMAT_SUBMASK can be used to separate the major and minor file
** types.
*/
enum
{ /* Major formats. */
SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */
SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */
SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */
SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */
SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */
SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */
SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */
SF_FORMAT_VOC = 0x080000, /* VOC files. */
SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */
SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */
SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */
SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */
SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */
SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */
SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */
SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */
SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */
SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */
SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */
SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */
SF_FORMAT_CAF = 0x180000, /* Core Audio File format */
/* Subtypes from here on. */
SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */
SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */
SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */
SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */
SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */
SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */
SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */
SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */
SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */
SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */
SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */
SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */
SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */
SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */
SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */
SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */
SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */
SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */
SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */
SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */
SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */
SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */
/* Endian-ness options. */
SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */
SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */
SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */
SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */
SF_FORMAT_SUBMASK = 0x0000FFFF,
SF_FORMAT_TYPEMASK = 0x0FFF0000,
SF_FORMAT_ENDMASK = 0x30000000
} ;
/*
** The following are the valid command numbers for the sf_command()
** interface. The use of these commands is documented in the file
** command.html in the doc directory of the source code distribution.
*/
enum
{ SFC_GET_LIB_VERSION = 0x1000,
SFC_GET_LOG_INFO = 0x1001,
SFC_GET_NORM_DOUBLE = 0x1010,
SFC_GET_NORM_FLOAT = 0x1011,
SFC_SET_NORM_DOUBLE = 0x1012,
SFC_SET_NORM_FLOAT = 0x1013,
SFC_SET_SCALE_FLOAT_INT_READ = 0x1014,
SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020,
SFC_GET_SIMPLE_FORMAT = 0x1021,
SFC_GET_FORMAT_INFO = 0x1028,
SFC_GET_FORMAT_MAJOR_COUNT = 0x1030,
SFC_GET_FORMAT_MAJOR = 0x1031,
SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032,
SFC_GET_FORMAT_SUBTYPE = 0x1033,
SFC_CALC_SIGNAL_MAX = 0x1040,
SFC_CALC_NORM_SIGNAL_MAX = 0x1041,
SFC_CALC_MAX_ALL_CHANNELS = 0x1042,
SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043,
SFC_GET_SIGNAL_MAX = 0x1044,
SFC_GET_MAX_ALL_CHANNELS = 0x1045,
SFC_SET_ADD_PEAK_CHUNK = 0x1050,
SFC_UPDATE_HEADER_NOW = 0x1060,
SFC_SET_UPDATE_HEADER_AUTO = 0x1061,
SFC_FILE_TRUNCATE = 0x1080,
SFC_SET_RAW_START_OFFSET = 0x1090,
SFC_SET_DITHER_ON_WRITE = 0x10A0,
SFC_SET_DITHER_ON_READ = 0x10A1,
SFC_GET_DITHER_INFO_COUNT = 0x10A2,
SFC_GET_DITHER_INFO = 0x10A3,
SFC_GET_EMBED_FILE_INFO = 0x10B0,
SFC_SET_CLIPPING = 0x10C0,
SFC_GET_CLIPPING = 0x10C1,
SFC_GET_INSTRUMENT = 0x10D0,
SFC_SET_INSTRUMENT = 0x10D1,
SFC_GET_LOOP_INFO = 0x10E0,
SFC_GET_BROADCAST_INFO = 0x10F0,
SFC_SET_BROADCAST_INFO = 0x10F1,
/* Following commands for testing only. */
SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001,
/*
** SFC_SET_ADD_* values are deprecated and will disappear at some
** time in the future. They are guaranteed to be here up to and
** including version 1.0.8 to avoid breakage of existng software.
** They currently do nothing and will continue to do nothing.
*/
SFC_SET_ADD_DITHER_ON_WRITE = 0x1070,
SFC_SET_ADD_DITHER_ON_READ = 0x1071
} ;
/*
** String types that can be set and read from files. Not all file types
** support this and even the file types which support one, may not support
** all string types.
*/
enum
{ SF_STR_TITLE = 0x01,
SF_STR_COPYRIGHT = 0x02,
SF_STR_SOFTWARE = 0x03,
SF_STR_ARTIST = 0x04,
SF_STR_COMMENT = 0x05,
SF_STR_DATE = 0x06
} ;
/*
** Use the following as the start and end index when doing metadata
** transcoding.
*/
#define SF_STR_FIRST SF_STR_TITLE
#define SF_STR_LAST SF_STR_DATE
enum
{ /* True and false */
SF_FALSE = 0,
SF_TRUE = 1,
/* Modes for opening files. */
SFM_READ = 0x10,
SFM_WRITE = 0x20,
SFM_RDWR = 0x30
} ;
/* Public error values. These are guaranteed to remain unchanged for the duration
** of the library major version number.
** There are also a large number of private error numbers which are internal to
** the library which can change at any time.
*/
enum
{ SF_ERR_NO_ERROR = 0,
SF_ERR_UNRECOGNISED_FORMAT = 1,
SF_ERR_SYSTEM = 2,
SF_ERR_MALFORMED_FILE = 3,
SF_ERR_UNSUPPORTED_ENCODING = 4
} ;
/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */
typedef struct SNDFILE_tag SNDFILE ;
/* The following typedef is system specific and is defined when libsndfile is.
** compiled. sf_count_t can be one of loff_t (Linux), off_t (*BSD),
** off64_t (Solaris), __int64_t (Win32) etc.
*/
typedef @TYPEOF_SF_COUNT_T@ sf_count_t ;
#define SF_COUNT_MAX @SF_COUNT_MAX@
/* A pointer to a SF_INFO structure is passed to sf_open_read () and filled in.
** On write, the SF_INFO structure is filled in by the user and passed into
** sf_open_write ().
*/
struct SF_INFO
{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */
int samplerate ;
int channels ;
int format ;
int sections ;
int seekable ;
} ;
typedef struct SF_INFO SF_INFO ;
/* The SF_FORMAT_INFO struct is used to retrieve information about the sound
** file formats libsndfile supports using the sf_command () interface.
**
** Using this interface will allow applications to support new file formats
** and encoding types when libsndfile is upgraded, without requiring
** re-compilation of the application.
**
** Please consult the libsndfile documentation (particularly the information
** on the sf_command () interface) for examples of its use.
*/
typedef struct
{ int format ;
const char *name ;
const char *extension ;
} SF_FORMAT_INFO ;
/*
** Enums and typedefs for adding dither on read and write.
** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE
** and SFC_SET_DITHER_ON_READ.
*/
enum
{ SFD_DEFAULT_LEVEL = 0,
SFD_CUSTOM_LEVEL = 0x40000000,
SFD_NO_DITHER = 500,
SFD_WHITE = 501,
SFD_TRIANGULAR_PDF = 502
} ;
typedef struct
{ int type ;
double level ;
const char *name ;
} SF_DITHER_INFO ;
/* Struct used to retrieve information about a file embedded within a
** larger file. See SFC_GET_EMBED_FILE_INFO.
*/
typedef struct
{ sf_count_t offset ;
sf_count_t length ;
} SF_EMBED_FILE_INFO ;
/*
** Structs used to retrieve music sample information from a file.
*/
enum
{ /*
** The loop mode field in SF_INSTRUMENT will be one of the following.
*/
SF_LOOP_NONE = 800,
SF_LOOP_FORWARD,
SF_LOOP_BACKWARD,
SF_LOOP_ALTERNATING
} ;
typedef struct
{ int gain ;
char basenote, detune ;
char velocity_lo, velocity_hi ;
char key_lo, key_hi ;
int loop_count ;
struct
{ int mode ;
unsigned int start ;
unsigned int end ;
unsigned int count ;
} loops [16] ; /* make variable in a sensible way */
} SF_INSTRUMENT ;
/* Struct used to retrieve loop information from a file.*/
typedef struct
{
short time_sig_num ; /* any positive integer > 0 */
short time_sig_den ; /* any positive power of 2 > 0 */
int loop_mode ; /* see SF_LOOP enum */
int num_beats ; /* this is NOT the amount of quarter notes !!!*/
/* a full bar of 4/4 is 4 beats */
/* a full bar of 7/8 is 7 beats */
float bpm ; /* suggestion, as it can be calculated using other fields:*/
/* file's lenght, file's sampleRate and our time_sig_den*/
/* -> bpms are always the amount of _quarter notes_ per minute */
int root_key ; /* MIDI note, or -1 for None */
int future [6] ;
} SF_LOOP_INFO ;
/* Struct used to retrieve broadcast (EBU) information from a file.
** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE.
*/
typedef struct
{ char description [256] ;
char originator [32] ;
char originator_reference [32] ;
char origination_date [10] ;
char origination_time [8] ;
int time_reference_low ;
int time_reference_high ;
short version ;
char umid [64] ;
char reserved [190] ;
unsigned int coding_history_size ;
char coding_history [256] ;
} SF_BROADCAST_INFO ;
typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ;
typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ;
typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ;
typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ;
typedef sf_count_t (*sf_vio_tell) (void *user_data) ;
struct SF_VIRTUAL_IO
{ sf_vio_get_filelen get_filelen ;
sf_vio_seek seek ;
sf_vio_read read ;
sf_vio_write write ;
sf_vio_tell tell ;
} ;
typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ;
/* Open the specified file for read, write or both. On error, this will
** return a NULL pointer. To find the error number, pass a NULL SNDFILE
** to sf_perror () or sf_error_str ().
** All calls to sf_open() should be matched with a call to sf_close().
*/
SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ;
/* Use the existing file descriptor to create a SNDFILE object. If close_desc
** is TRUE, the file descriptor will be closed when sf_close() is called. If
** it is FALSE, the descritor will not be closed.
** When passed a descriptor like this, the library will assume that the start
** of file header is at the current file offset. This allows sound files within
** larger container files to be read and/or written.
** On error, this will return a NULL pointer. To find the error number, pass a
** NULL SNDFILE to sf_perror () or sf_error_str ().
** All calls to sf_open_fd() should be matched with a call to sf_close().
*/
SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
/* sf_error () returns a error number which can be translated to a text
** string using sf_error_number().
*/
int sf_error (SNDFILE *sndfile) ;
/* sf_strerror () returns to the caller a pointer to the current error message for
** the given SNDFILE.
*/
const char* sf_strerror (SNDFILE *sndfile) ;
/* sf_error_number () allows the retrieval of the error string for each internal
** error number.
**
*/
const char* sf_error_number (int errnum) ;
/* The following three error functions are deprecated but they will remain in the
** library for the forseeable future. The function sf_strerror() should be used
** in their place.
*/
int sf_perror (SNDFILE *sndfile) ;
int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ;
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ;
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
int sf_format_check (const SF_INFO *info) ;
/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
** stdio.h function fseek ().
** An offset of zero with whence set to SEEK_SET will position the
** read / write pointer to the first data sample.
** On success sf_seek returns the current position in (multi-channel)
** samples from the start of the file.
** Please see the libsndfile documentation for moving the read pointer
** separately from the write pointer on files open in mode SFM_RDWR.
** On error all of these functions return -1.
*/
sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ;
/* Functions for retrieving and setting string data within sound files.
** Not all file types support this features; AIFF and WAV do. For both
** functions, the str_type parameter must be one of the SF_STR_* values
** defined above.
** On error, sf_set_string() returns non-zero while sf_get_string()
** returns NULL.
*/
int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ;
const char* sf_get_string (SNDFILE *sndfile, int str_type) ;
/* Functions for reading/writing the waveform data of a sound file.
*/
sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ;
/* Functions for reading and writing the data chunk in terms of frames.
** The number of items actually read/written = frames * number of channels.
** sf_xxxx_raw read/writes the raw data bytes from/to the file
** sf_xxxx_short passes data in the native short format
** sf_xxxx_int passes data in the native int format
** sf_xxxx_float passes data in the native float format
** sf_xxxx_double passes data in the native double format
** All of these read/write function return number of frames read/written.
*/
sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ;
sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ;
sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ;
sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ;
/* Functions for reading and writing the data chunk in terms of items.
** Otherwise similar to above.
** All of these read/write function return number of items read/written.
*/
sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ;
sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ;
sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ;
sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ;
/* Close the SNDFILE and clean up all memory allocations associated with this
** file.
** Returns 0 on success, or an error number.
*/
int sf_close (SNDFILE *sndfile) ;
/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file
** to force the writing of data to disk. If the file is opened SFM_READ
** no action is taken.
*/
void sf_write_sync (SNDFILE *sndfile) ;
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* SNDFILE_H */

View File

@@ -0,0 +1 @@
timestamp for src/config.h

View File

@@ -0,0 +1,204 @@
/*
** Copyright (C) 2001-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "sndfile.h"
#include "common.h"
#define STRINGS_DEBUG 0
#if STRINGS_DEBUG
static void hexdump (void *data, int len) ;
#endif
int
psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
{ static char lsf_name [] = PACKAGE "-" VERSION ;
static char bracket_name [] = " (" PACKAGE "-" VERSION ")" ;
int k, str_len, len_remaining, str_flags ;
if (str == NULL)
return SFE_STR_BAD_STRING ;
str_len = strlen (str) ;
/* A few extra checks for write mode. */
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->str_flags & SF_STR_ALLOW_START) == 0)
return SFE_STR_NO_SUPPORT ;
if ((psf->str_flags & SF_STR_ALLOW_END) == 0)
return SFE_STR_NO_SUPPORT ;
/* Only allow zero length strings for software. */
if (str_type != SF_STR_SOFTWARE && str_len == 0)
return SFE_STR_BAD_STRING ;
} ;
/* Determine flags */
str_flags = SF_STR_LOCATE_START ;
if (psf->have_written)
{ if ((psf->str_flags & SF_STR_ALLOW_END) == 0)
return SFE_STR_NO_ADD_END ;
str_flags = SF_STR_LOCATE_END ;
} ;
/* Find next free slot in table. */
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
if (psf->strings [k].type == 0)
break ;
/* More sanity checking. */
if (k >= SF_MAX_STRINGS)
return SFE_STR_MAX_COUNT ;
if (k == 0 && psf->str_end != NULL)
{ psf_log_printf (psf, "SFE_STR_WEIRD : k == 0 && psf->str_end != NULL\n") ;
return SFE_STR_WEIRD ;
} ;
if (k != 0 && psf->str_end == NULL)
{ psf_log_printf (psf, "SFE_STR_WEIRD : k != 0 && psf->str_end == NULL\n") ;
return SFE_STR_WEIRD ;
} ;
/* Special case for the first string. */
if (k == 0)
psf->str_end = psf->str_storage ;
#if STRINGS_DEBUG
psf_log_printf (psf, "str_storage : %X\n", (int) psf->str_storage) ;
psf_log_printf (psf, "str_end : %X\n", (int) psf->str_end) ;
psf_log_printf (psf, "sizeof (str_storage) : %d\n", SIGNED_SIZEOF (psf->str_storage)) ;
#endif
len_remaining = SIGNED_SIZEOF (psf->str_storage) - (psf->str_end - psf->str_storage) ;
if (len_remaining < str_len + 2)
return SFE_STR_MAX_DATA ;
switch (str_type)
{ case SF_STR_SOFTWARE :
/* In write mode, want to append libsndfile-version to string. */
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->strings [k].type = str_type ;
psf->strings [k].str = psf->str_end ;
psf->strings [k].flags = str_flags ;
memcpy (psf->str_end, str, str_len + 1) ;
psf->str_end += str_len ;
/*
** If the supplied string does not already contain a
** libsndfile-X.Y.Z component, then add it.
*/
if (strstr (str, PACKAGE) == NULL && len_remaining > (int) (strlen (bracket_name) + str_len + 2))
{ if (strlen (str) == 0)
strncat (psf->str_end, lsf_name, len_remaining) ;
else
strncat (psf->str_end, bracket_name, len_remaining) ;
psf->str_end += strlen (psf->str_end) ;
} ;
/* Plus one to catch string terminator. */
psf->str_end += 1 ;
break ;
} ;
/* Fall though if not write mode. */
case SF_STR_TITLE :
case SF_STR_COPYRIGHT :
case SF_STR_ARTIST :
case SF_STR_COMMENT :
case SF_STR_DATE :
psf->strings [k].type = str_type ;
psf->strings [k].str = psf->str_end ;
psf->strings [k].flags = str_flags ;
/* Plus one to catch string terminator. */
memcpy (psf->str_end, str, str_len + 1) ;
psf->str_end += str_len + 1 ;
break ;
default :
return SFE_STR_BAD_TYPE ;
} ;
psf->str_flags |= (psf->have_written) ? SF_STR_LOCATE_END : SF_STR_LOCATE_START ;
#if STRINGS_DEBUG
hexdump (psf->str_storage, 300) ;
#endif
return 0 ;
} /* psf_store_string */
int
psf_set_string (SF_PRIVATE *psf, int str_type, const char *str)
{ if (psf->mode == SFM_READ)
return SFE_STR_NOT_WRITE ;
return psf_store_string (psf, str_type, str) ;
} /* psf_set_string */
const char*
psf_get_string (SF_PRIVATE *psf, int str_type)
{ int k ;
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
if (str_type == psf->strings [k].type)
return psf->strings [k].str ;
return NULL ;
} /* psf_get_string */
#if STRINGS_DEBUG
#include <ctype.h>
static void
hexdump (void *data, int len)
{ unsigned char *ptr ;
int k ;
ptr = data ;
puts ("---------------------------------------------------------") ;
while (len >= 16)
{ for (k = 0 ; k < 16 ; k++)
printf ("%02X ", ptr [k] & 0xFF) ;
printf (" ") ;
for (k = 0 ; k < 16 ; k++)
printf ("%c", isprint (ptr [k]) ? ptr [k] : '.') ;
puts ("") ;
ptr += 16 ;
len -= 16 ;
} ;
} /* hexdump */
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 04393aa1-9389-46fe-baf2-58a7bd544fd6
*/

410
libs/libsndfile/src/svx.c Normal file
View File

@@ -0,0 +1,410 @@
/*
** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*------------------------------------------------------------------------------
* Macros to handle big/little endian issues.
*/
#define FORM_MARKER (MAKE_MARKER ('F', 'O', 'R', 'M'))
#define SVX8_MARKER (MAKE_MARKER ('8', 'S', 'V', 'X'))
#define SV16_MARKER (MAKE_MARKER ('1', '6', 'S', 'V'))
#define VHDR_MARKER (MAKE_MARKER ('V', 'H', 'D', 'R'))
#define BODY_MARKER (MAKE_MARKER ('B', 'O', 'D', 'Y'))
#define ATAK_MARKER (MAKE_MARKER ('A', 'T', 'A', 'K'))
#define RLSE_MARKER (MAKE_MARKER ('R', 'L', 'S', 'E'))
#define c_MARKER (MAKE_MARKER ('(', 'c', ')', ' '))
#define NAME_MARKER (MAKE_MARKER ('N', 'A', 'M', 'E'))
#define AUTH_MARKER (MAKE_MARKER ('A', 'U', 'T', 'H'))
#define ANNO_MARKER (MAKE_MARKER ('A', 'N', 'N', 'O'))
#define CHAN_MARKER (MAKE_MARKER ('C', 'H', 'A', 'N'))
/*------------------------------------------------------------------------------
* Typedefs for file chunks.
*/
typedef struct
{ unsigned int oneShotHiSamples, repeatHiSamples, samplesPerHiCycle ;
unsigned short samplesPerSec ;
unsigned char octave, compression ;
unsigned int volume ;
} VHDR_CHUNK ;
enum {
HAVE_FORM = 0x01,
HAVE_SVX = 0x02,
HAVE_VHDR = 0x04,
HAVE_BODY = 0x08
} ;
/*------------------------------------------------------------------------------
* Private static functions.
*/
static int svx_close (SF_PRIVATE *psf) ;
static int svx_write_header (SF_PRIVATE *psf, int calc_length) ;
static int svx_read_header (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
svx_open (SF_PRIVATE *psf)
{ int error ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = svx_read_header (psf)))
return error ;
psf->endian = SF_ENDIAN_BIG ; /* All SVX files are big endian. */
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
if (psf->blockwidth)
psf->sf.frames = psf->datalength / psf->blockwidth ;
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
} ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SVX)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
if (psf->endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU))
return SFE_BAD_ENDIAN ;
psf->endian = SF_ENDIAN_BIG ; /* All SVX files are big endian. */
error = svx_write_header (psf, SF_FALSE) ;
if (error)
return error ;
psf->write_header = svx_write_header ;
} ;
psf->container_close = svx_close ;
if ((error = pcm_init (psf)))
return error ;
return 0 ;
} /* svx_open */
/*------------------------------------------------------------------------------
*/
static int
svx_read_header (SF_PRIVATE *psf)
{ VHDR_CHUNK vhdr ;
unsigned int FORMsize, vhdrsize, dword, marker ;
int filetype = 0, parsestage = 0, done = 0 ;
int bytecount = 0, channels ;
memset (&vhdr, 0, sizeof (vhdr)) ;
psf_binheader_readf (psf, "p", 0) ;
/* Set default number of channels. Currently can't handle stereo SVX files. */
psf->sf.channels = 1 ;
psf->sf.format = SF_FORMAT_SVX ;
while (! done)
{ psf_binheader_readf (psf, "m", &marker) ;
switch (marker)
{ case FORM_MARKER :
if (parsestage)
return SFE_SVX_NO_FORM ;
psf_binheader_readf (psf, "E4", &FORMsize) ;
if (FORMsize != psf->filelength - 2 * sizeof (dword))
{ dword = psf->filelength - 2 * sizeof (dword) ;
psf_log_printf (psf, "FORM : %d (should be %d)\n", FORMsize, dword) ;
FORMsize = dword ;
}
else
psf_log_printf (psf, "FORM : %d\n", FORMsize) ;
parsestage |= HAVE_FORM ;
break ;
case SVX8_MARKER :
case SV16_MARKER :
if (! (parsestage & HAVE_FORM))
return SFE_SVX_NO_FORM ;
filetype = marker ;
psf_log_printf (psf, " %M\n", marker) ;
parsestage |= HAVE_SVX ;
break ;
case VHDR_MARKER :
if (! (parsestage & (HAVE_FORM | HAVE_SVX)))
return SFE_SVX_NO_FORM ;
psf_binheader_readf (psf, "E4", &vhdrsize) ;
psf_log_printf (psf, " VHDR : %d\n", vhdrsize) ;
psf_binheader_readf (psf, "E4442114", &(vhdr.oneShotHiSamples), &(vhdr.repeatHiSamples),
&(vhdr.samplesPerHiCycle), &(vhdr.samplesPerSec), &(vhdr.octave), &(vhdr.compression),
&(vhdr.volume)) ;
psf_log_printf (psf, " OneShotHiSamples : %d\n", vhdr.oneShotHiSamples) ;
psf_log_printf (psf, " RepeatHiSamples : %d\n", vhdr.repeatHiSamples) ;
psf_log_printf (psf, " samplesPerHiCycle : %d\n", vhdr.samplesPerHiCycle) ;
psf_log_printf (psf, " Sample Rate : %d\n", vhdr.samplesPerSec) ;
psf_log_printf (psf, " Octave : %d\n", vhdr.octave) ;
psf_log_printf (psf, " Compression : %d => ", vhdr.compression) ;
switch (vhdr.compression)
{ case 0 : psf_log_printf (psf, "None.\n") ;
break ;
case 1 : psf_log_printf (psf, "Fibonacci delta\n") ;
break ;
case 2 : psf_log_printf (psf, "Exponential delta\n") ;
break ;
} ;
psf_log_printf (psf, " Volume : %d\n", vhdr.volume) ;
psf->sf.samplerate = vhdr.samplesPerSec ;
if (filetype == SVX8_MARKER)
{ psf->sf.format |= SF_FORMAT_PCM_S8 ;
psf->bytewidth = 1 ;
}
else if (filetype == SV16_MARKER)
{ psf->sf.format |= SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
} ;
parsestage |= HAVE_VHDR ;
break ;
case BODY_MARKER :
if (! (parsestage & HAVE_VHDR))
return SFE_SVX_NO_BODY ;
psf_binheader_readf (psf, "E4", &dword) ;
psf->datalength = dword ;
psf->dataoffset = psf_ftell (psf) ;
if (psf->datalength > psf->filelength - psf->dataoffset)
{ psf_log_printf (psf, " BODY : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ;
psf->datalength = psf->filelength - psf->dataoffset ;
}
else
psf_log_printf (psf, " BODY : %D\n", psf->datalength) ;
parsestage |= HAVE_BODY ;
if (! psf->sf.seekable)
break ;
psf_fseek (psf, psf->datalength, SEEK_CUR) ;
break ;
case NAME_MARKER :
if (! (parsestage & HAVE_SVX))
return SFE_SVX_NO_FORM ;
psf_binheader_readf (psf, "E4", &dword) ;
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
if (strlen (psf->filename) != dword)
{ if (dword > sizeof (psf->filename) - 1)
return SFE_SVX_BAD_NAME_LENGTH ;
psf_binheader_readf (psf, "b", psf->filename, dword) ;
psf->filename [dword] = 0 ;
}
else
psf_binheader_readf (psf, "j", dword) ;
break ;
case ANNO_MARKER :
if (! (parsestage & HAVE_SVX))
return SFE_SVX_NO_FORM ;
psf_binheader_readf (psf, "E4", &dword) ;
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
psf_binheader_readf (psf, "j", dword) ;
break ;
case CHAN_MARKER :
if (! (parsestage & HAVE_SVX))
return SFE_SVX_NO_FORM ;
psf_binheader_readf (psf, "E4", &dword) ;
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
bytecount += psf_binheader_readf (psf, "E4", &channels) ;
psf->sf.channels = channels ;
psf_log_printf (psf, " Channels : %d\n", channels) ;
psf_binheader_readf (psf, "j", dword - bytecount) ;
break ;
case AUTH_MARKER :
case c_MARKER :
if (! (parsestage & HAVE_SVX))
return SFE_SVX_NO_FORM ;
psf_binheader_readf (psf, "E4", &dword) ;
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
psf_binheader_readf (psf, "j", dword) ;
break ;
default :
if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF)
&& isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF))
{ psf_binheader_readf (psf, "E4", &dword) ;
psf_log_printf (psf, "%M : %d (unknown marker)\n", marker, dword) ;
psf_binheader_readf (psf, "j", dword) ;
break ;
} ;
if ((dword = psf_ftell (psf)) & 0x03)
{ psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ;
psf_binheader_readf (psf, "j", -3) ;
break ;
} ;
psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ;
done = 1 ;
} ; /* switch (marker) */
if (! psf->sf.seekable && (parsestage & HAVE_BODY))
break ;
if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (dword))
break ;
} ; /* while (1) */
if (vhdr.compression)
return SFE_SVX_BAD_COMP ;
if (psf->dataoffset <= 0)
return SFE_SVX_NO_DATA ;
return 0 ;
} /* svx_read_header */
static int
svx_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
svx_write_header (psf, SF_TRUE) ;
return 0 ;
} /* svx_close */
static int
svx_write_header (SF_PRIVATE *psf, int calc_length)
{ static char annotation [] = "libsndfile by Erik de Castro Lopo\0\0\0" ;
sf_count_t current ;
current = psf_ftell (psf) ;
if (calc_length)
{ psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->dataend)
psf->datalength -= psf->filelength - psf->dataend ;
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
} ;
psf->header [0] = 0 ;
psf->headindex = 0 ;
psf_fseek (psf, 0, SEEK_SET) ;
/* FORM marker and FORM size. */
psf_binheader_writef (psf, "Etm8", FORM_MARKER, (psf->filelength < 8) ?
psf->filelength * 0 : psf->filelength - 8) ;
psf_binheader_writef (psf, "m", (psf->bytewidth == 1) ? SVX8_MARKER : SV16_MARKER) ;
/* VHDR chunk. */
psf_binheader_writef (psf, "Em4", VHDR_MARKER, sizeof (VHDR_CHUNK)) ;
/* VHDR : oneShotHiSamples, repeatHiSamples, samplesPerHiCycle */
psf_binheader_writef (psf, "E444", psf->sf.frames, 0, 0) ;
/* VHDR : samplesPerSec, octave, compression */
psf_binheader_writef (psf, "E211", psf->sf.samplerate, 1, 0) ;
/* VHDR : volume */
psf_binheader_writef (psf, "E4", (psf->bytewidth == 1) ? 0xFF : 0xFFFF) ;
/* Filename and annotation strings. */
psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->filename, ANNO_MARKER, annotation) ;
/* BODY marker and size. */
psf_binheader_writef (psf, "Etm8", BODY_MARKER, (psf->datalength < 0) ?
psf->datalength * 0 : psf->datalength) ;
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
if (psf->error)
return psf->error ;
psf->dataoffset = psf->headindex ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* svx_write_header */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a80ab6fb-7d75-4d32-a6b0-0061a3f05d95
*/

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