mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Added support for replaying DVDs
This commit is contained in:
parent
1962940c39
commit
bff17fb1d0
@ -106,3 +106,9 @@ Ulrich R
|
|||||||
|
|
||||||
Helmut Schächner <schaechner@yahoo.com>
|
Helmut Schächner <schaechner@yahoo.com>
|
||||||
for his support in keeping the Premiere World channels up to date in 'channels.conf'
|
for his support in keeping the Premiere World channels up to date in 'channels.conf'
|
||||||
|
|
||||||
|
Andreas Schultz <aschultz@warp10.net>
|
||||||
|
for adding support for replaying DVDs
|
||||||
|
|
||||||
|
Aaron Holtzman
|
||||||
|
for writing 'ac3dec'
|
||||||
|
5
HISTORY
5
HISTORY
@ -610,7 +610,10 @@ Video Disk Recorder Revision History
|
|||||||
- Explicitly switching back to the previously active channel after ending a
|
- Explicitly switching back to the previously active channel after ending a
|
||||||
replay session (to have it shown correctly in case it was in 'Transfer Mode').
|
replay session (to have it shown correctly in case it was in 'Transfer Mode').
|
||||||
|
|
||||||
2001-07-31: Version 0.86
|
2001-08-03: Version 0.86
|
||||||
|
|
||||||
- Modified the display of the channel group separators (thanks to Markus Lang
|
- Modified the display of the channel group separators (thanks to Markus Lang
|
||||||
for this suggestion).
|
for this suggestion).
|
||||||
|
- Added support for replaying DVDs (thanks to Andreas Schultz). VDR now needs
|
||||||
|
the 'libdvdread' library to be installed.
|
||||||
|
|
||||||
|
18
INSTALL
18
INSTALL
@ -15,6 +15,11 @@ If you have the DVB driver source in a different location
|
|||||||
you will have to change the definition of DVBDIR in the
|
you will have to change the definition of DVBDIR in the
|
||||||
Makefile.
|
Makefile.
|
||||||
|
|
||||||
|
VDR also needs the package 'libdvdread' in order to replay DVDs.
|
||||||
|
This package is expected to be located in the directory ../DVD (seen
|
||||||
|
from the VDR directory). Adjust the definition of DVDDIR in the
|
||||||
|
Makefile if necessary.
|
||||||
|
|
||||||
This program requires the card driver version 0.9.0 or higher
|
This program requires the card driver version 0.9.0 or higher
|
||||||
to work properly. You need to load the dvb.o module *without* option
|
to work properly. You need to load the dvb.o module *without* option
|
||||||
'outstream=0' (previous versions of VDR required this option to have
|
'outstream=0' (previous versions of VDR required this option to have
|
||||||
@ -100,6 +105,19 @@ This program must be given to VDR with the '-a' option, as in
|
|||||||
|
|
||||||
vdr -a ac3play
|
vdr -a ac3play
|
||||||
|
|
||||||
|
Accessing the DVD drive:
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
By default VDR expects the DVD drive to be located at /dev/dvd (which
|
||||||
|
typically is a symbolic link to the actual device, for instance /dev/hdc).
|
||||||
|
You can use the '-V' option to overwrite this, as in
|
||||||
|
|
||||||
|
vdr -V /media/dvd
|
||||||
|
|
||||||
|
Note that the user id under which VDR runs needs to have write access to
|
||||||
|
the DVD device in order to replay CSS protected DVDs (which also requires
|
||||||
|
the presence of the 'libcss' library).
|
||||||
|
|
||||||
The video data directory:
|
The video data directory:
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
2
MANUAL
2
MANUAL
@ -19,7 +19,7 @@ Video Disk Recorder User's Manual
|
|||||||
Back - Menu off Main menu Main menu Discard Main menu Recordings menu
|
Back - Menu off Main menu Main menu Discard Main menu Recordings menu
|
||||||
Red - Record Edit Edit - Play -
|
Red - Record Edit Edit - Play -
|
||||||
Green - Language New New - Rewind Skip -60s
|
Green - Language New New - Rewind Skip -60s
|
||||||
Yellow - - Delete Delete - Delete Skip +60s
|
Yellow - Eject DVD Delete Delete - Delete Skip +60s
|
||||||
Blue - Resume Mark Mark - Summary Stop
|
Blue - Resume Mark Mark - Summary Stop
|
||||||
0..9 Ch select - - - Numeric inp. - Editing
|
0..9 Ch select - - - Numeric inp. - Editing
|
||||||
|
|
||||||
|
47
Makefile
47
Makefile
@ -4,18 +4,24 @@
|
|||||||
# See the main source file 'vdr.c' for copyright information and
|
# See the main source file 'vdr.c' for copyright information and
|
||||||
# how to reach the author.
|
# how to reach the author.
|
||||||
#
|
#
|
||||||
# $Id: Makefile 1.22 2001/06/02 09:15:39 kls Exp $
|
# $Id: Makefile 1.23 2001/08/03 13:10:52 kls Exp $
|
||||||
|
|
||||||
DVBDIR = ../DVB
|
DVBDIR = ../DVB
|
||||||
|
DVDDIR = ../DVD
|
||||||
|
AC3DIR = ./ac3dec
|
||||||
|
|
||||||
INCLUDES = -I$(DVBDIR)/ost/include
|
INCLUDES = -I$(DVBDIR)/ost/include -I$(DVDDIR)/libdvdread
|
||||||
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o osd.o\
|
LIBDIRS = -L$(DVDDIR)/libdvdread/dvdread/.libs
|
||||||
|
|
||||||
|
OBJS = config.o dvbapi.o dvbosd.o dvd.o eit.o font.o i18n.o interface.o menu.o osd.o\
|
||||||
recording.o remote.o remux.o ringbuffer.o svdrp.o thread.o tools.o vdr.o\
|
recording.o remote.o remux.o ringbuffer.o svdrp.o thread.o tools.o vdr.o\
|
||||||
videodir.o
|
videodir.o
|
||||||
|
|
||||||
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
||||||
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
|
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
|
||||||
|
|
||||||
|
DEFINES += -D_LARGEFILE64_SOURCE
|
||||||
|
|
||||||
ifndef REMOTE
|
ifndef REMOTE
|
||||||
REMOTE = KBD
|
REMOTE = KBD
|
||||||
endif
|
endif
|
||||||
@ -42,29 +48,30 @@ font: genfontfile fontfix.c fontosd.c
|
|||||||
|
|
||||||
# Dependencies:
|
# Dependencies:
|
||||||
|
|
||||||
config.o : config.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
|
config.o : config.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
|
||||||
dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h eit.h font.h recording.h remux.h ringbuffer.h thread.h tools.h videodir.h
|
dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h recording.h remux.h ringbuffer.h thread.h tools.h videodir.h
|
||||||
dvbosd.o : dvbosd.c dvbosd.h font.h tools.h
|
dvbosd.o : dvbosd.c dvbosd.h font.h tools.h
|
||||||
eit.o : eit.c config.h dvbapi.h dvbosd.h eit.h font.h thread.h tools.h videodir.h
|
dvd.o : dvd.c dvd.h
|
||||||
|
eit.o : eit.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h thread.h tools.h videodir.h
|
||||||
font.o : font.c font.h fontfix.c fontosd.c tools.h
|
font.o : font.c font.h fontfix.c fontosd.c tools.h
|
||||||
i18n.o : i18n.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h thread.h tools.h
|
i18n.o : i18n.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h thread.h tools.h
|
||||||
interface.o : interface.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
|
interface.o : interface.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
|
||||||
menu.o : menu.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h
|
menu.o : menu.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h
|
||||||
osd.o : osd.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h osd.h remote.h svdrp.h thread.h tools.h
|
osd.o : osd.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h osd.h remote.h svdrp.h thread.h tools.h
|
||||||
recording.o : recording.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
|
recording.o : recording.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h interface.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
|
||||||
remote.o : remote.c config.h dvbapi.h dvbosd.h eit.h font.h remote.h thread.h tools.h
|
remote.o : remote.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h remote.h thread.h tools.h
|
||||||
remux.o : remux.c remux.h thread.h tools.h
|
remux.o : remux.c remux.h thread.h tools.h
|
||||||
ringbuffer.o: ringbuffer.c ringbuffer.h thread.h tools.h
|
ringbuffer.o: ringbuffer.c ringbuffer.h thread.h tools.h
|
||||||
svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h
|
svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h
|
||||||
thread.o : thread.c thread.h tools.h
|
thread.o : thread.c thread.h tools.h
|
||||||
tools.o : tools.c tools.h
|
tools.o : tools.c tools.h
|
||||||
vdr.o : vdr.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
|
vdr.o : vdr.c config.h dvbapi.h dvbosd.h dvd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
|
||||||
videodir.o : videodir.c tools.h videodir.h
|
videodir.o : videodir.c tools.h videodir.h
|
||||||
|
|
||||||
# The main program:
|
# The main program:
|
||||||
|
|
||||||
vdr: $(OBJS)
|
vdr: $(OBJS) $(AC3DIR)/libac3.a
|
||||||
g++ -g -O2 $(OBJS) -lncurses -ljpeg -lpthread -o vdr
|
g++ -g -O2 $(OBJS) -lncurses -ljpeg -lpthread $(LIBDIRS) -ldvdread $(AC3DIR)/libac3.a -o vdr
|
||||||
|
|
||||||
# The font files:
|
# The font files:
|
||||||
|
|
||||||
@ -80,9 +87,15 @@ genfontfile.o: genfontfile.c
|
|||||||
genfontfile: genfontfile.o
|
genfontfile: genfontfile.o
|
||||||
gcc -o $@ -L/usr/X11R6/lib $< -lX11
|
gcc -o $@ -L/usr/X11R6/lib $< -lX11
|
||||||
|
|
||||||
|
# The ac3dec library:
|
||||||
|
|
||||||
|
$(AC3DIR)/libac3.a:
|
||||||
|
make -C $(AC3DIR) all
|
||||||
|
|
||||||
# Housekeeping:
|
# Housekeeping:
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm -f $(OBJS) vdr genfontfile genfontfile.o core
|
make -C $(AC3DIR) clean
|
||||||
|
-rm -f $(OBJS) vdr genfontfile genfontfile.o core *~
|
||||||
CLEAN: clean
|
CLEAN: clean
|
||||||
-rm -f fontfix.c fontosd.c
|
-rm -f fontfix.c fontosd.c
|
||||||
|
22
ac3dec/Makefile
Normal file
22
ac3dec/Makefile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# Makefile for 'ac3dec'
|
||||||
|
#
|
||||||
|
# $Id: Makefile 1.1 2001/08/02 13:18:08 kls Exp $
|
||||||
|
|
||||||
|
OBJS = coeff.o decode.o exponent.o rematrix.o bit_allocate.o crc.o dither.o\
|
||||||
|
imdct.o sanity_check.o bitstream.o debug.o downmix.o parse.o stats.o
|
||||||
|
|
||||||
|
DEFINES += -DDOLBY_SURROUND
|
||||||
|
|
||||||
|
all: libac3.a
|
||||||
|
|
||||||
|
libac3.a: $(OBJS)
|
||||||
|
ar -rc libac3.a $(OBJS)
|
||||||
|
|
||||||
|
# Implicit rules:
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
gcc -g -O2 -Wall -m486 -c $(DEFINES) $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~ libac3.a $(OBJS)
|
60
ac3dec/ac3.h
Normal file
60
ac3dec/ac3.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* ac3.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AARONS_TYPES
|
||||||
|
#define AARONS_TYPES
|
||||||
|
typedef unsigned long long uint_64;
|
||||||
|
typedef unsigned int uint_32;
|
||||||
|
typedef unsigned short uint_16;
|
||||||
|
typedef unsigned char uint_8;
|
||||||
|
|
||||||
|
typedef signed long long sint_64;
|
||||||
|
typedef signed int sint_32;
|
||||||
|
typedef signed short sint_16;
|
||||||
|
typedef signed char sint_8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AC3_DOLBY_SURR_ENABLE 0x1
|
||||||
|
#define AC3_3DNOW_ENABLE 0x2
|
||||||
|
#define AC3_MMX_ENABLE 0x4
|
||||||
|
#define AC3_ALTIVEC_ENABLE 0x8
|
||||||
|
|
||||||
|
typedef struct ac3_config_s
|
||||||
|
{
|
||||||
|
//Bit flags that enable various things
|
||||||
|
uint_32 flags;
|
||||||
|
//Callback that points the decoder to new stream data
|
||||||
|
void (*fill_buffer_callback)(uint_8 **, uint_8 **);
|
||||||
|
//Number of discrete channels in final output (for downmixing)
|
||||||
|
uint_16 num_output_ch;
|
||||||
|
//Which channel of a dual mono stream to select
|
||||||
|
uint_16 dual_mono_ch_sel;
|
||||||
|
} ac3_config_t;
|
||||||
|
|
||||||
|
void ac3_init(ac3_config_t *);
|
||||||
|
uint_32 ac3_decode_data(uint_8 *data_start,uint_8 *data_end, int ac3reset, int *input_pointer, int *output_pointer, char *ac3_data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
344
ac3dec/ac3_internal.h
Normal file
344
ac3dec/ac3_internal.h
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
/*
|
||||||
|
* ac3_internal.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#define inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Exponent strategy constants */
|
||||||
|
#define EXP_REUSE (0)
|
||||||
|
#define EXP_D15 (1)
|
||||||
|
#define EXP_D25 (2)
|
||||||
|
#define EXP_D45 (3)
|
||||||
|
|
||||||
|
/* Delta bit allocation constants */
|
||||||
|
#define DELTA_BIT_REUSE (0)
|
||||||
|
#define DELTA_BIT_NEW (1)
|
||||||
|
#define DELTA_BIT_NONE (2)
|
||||||
|
#define DELTA_BIT_RESERVED (3)
|
||||||
|
|
||||||
|
/* samples work structure */
|
||||||
|
typedef float stream_samples_t[6][256];
|
||||||
|
|
||||||
|
/* global config structure */
|
||||||
|
extern ac3_config_t ac3_config;
|
||||||
|
/* global error flag */
|
||||||
|
extern uint_32 error_flag;
|
||||||
|
|
||||||
|
/* Everything you wanted to know about band structure */
|
||||||
|
/*
|
||||||
|
* The entire frequency domain is represented by 256 real
|
||||||
|
* floating point fourier coefficients. Only the lower 253
|
||||||
|
* coefficients are actually utilized however. We use arrays
|
||||||
|
* of 256 to be efficient in some cases.
|
||||||
|
*
|
||||||
|
* The 5 full bandwidth channels (fbw) can have their higher
|
||||||
|
* frequencies coupled together. These coupled channels then
|
||||||
|
* share their high frequency components.
|
||||||
|
*
|
||||||
|
* This coupling band is broken up into 18 sub-bands starting
|
||||||
|
* at mantissa number 37. Each sub-band is 12 bins wide.
|
||||||
|
*
|
||||||
|
* There are 50 bit allocation sub-bands which cover the entire
|
||||||
|
* frequency range. The sub-bands are of non-uniform width, and
|
||||||
|
* approximate a 1/6 octave scale.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The following structures are filled in by their corresponding parse_*
|
||||||
|
* functions. See http://www.atsc.org/Standards/A52/a_52.pdf for
|
||||||
|
* full details on each field. Indented fields are used to denote
|
||||||
|
* conditional fields.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct syncinfo_s
|
||||||
|
{
|
||||||
|
uint_32 magic;
|
||||||
|
/* Sync word == 0x0B77 */
|
||||||
|
uint_16 syncword;
|
||||||
|
/* crc for the first 5/8 of the sync block */
|
||||||
|
/* uint_16 crc1; */
|
||||||
|
/* Stream Sampling Rate (kHz) 0 = 48, 1 = 44.1, 2 = 32, 3 = reserved */
|
||||||
|
uint_16 fscod;
|
||||||
|
/* Frame size code */
|
||||||
|
uint_16 frmsizecod;
|
||||||
|
|
||||||
|
/* Information not in the AC-3 bitstream, but derived */
|
||||||
|
/* Frame size in 16 bit words */
|
||||||
|
uint_16 frame_size;
|
||||||
|
/* Bit rate in kilobits */
|
||||||
|
uint_16 bit_rate;
|
||||||
|
/* sampling rate in hertz */
|
||||||
|
uint_32 sampling_rate;
|
||||||
|
|
||||||
|
} syncinfo_t;
|
||||||
|
|
||||||
|
typedef struct bsi_s
|
||||||
|
{
|
||||||
|
uint_32 magic;
|
||||||
|
/* Bit stream identification == 0x8 */
|
||||||
|
uint_16 bsid;
|
||||||
|
/* Bit stream mode */
|
||||||
|
uint_16 bsmod;
|
||||||
|
/* Audio coding mode */
|
||||||
|
uint_16 acmod;
|
||||||
|
/* If we're using the centre channel then */
|
||||||
|
/* centre mix level */
|
||||||
|
uint_16 cmixlev;
|
||||||
|
/* If we're using the surround channel then */
|
||||||
|
/* surround mix level */
|
||||||
|
uint_16 surmixlev;
|
||||||
|
/* If we're in 2/0 mode then */
|
||||||
|
/* Dolby surround mix level - NOT USED - */
|
||||||
|
uint_16 dsurmod;
|
||||||
|
/* Low frequency effects on */
|
||||||
|
uint_16 lfeon;
|
||||||
|
/* Dialogue Normalization level */
|
||||||
|
uint_16 dialnorm;
|
||||||
|
/* Compression exists */
|
||||||
|
uint_16 compre;
|
||||||
|
/* Compression level */
|
||||||
|
uint_16 compr;
|
||||||
|
/* Language code exists */
|
||||||
|
uint_16 langcode;
|
||||||
|
/* Language code */
|
||||||
|
uint_16 langcod;
|
||||||
|
/* Audio production info exists*/
|
||||||
|
uint_16 audprodie;
|
||||||
|
uint_16 mixlevel;
|
||||||
|
uint_16 roomtyp;
|
||||||
|
/* If we're in dual mono mode (acmod == 0) then extra stuff */
|
||||||
|
uint_16 dialnorm2;
|
||||||
|
uint_16 compr2e;
|
||||||
|
uint_16 compr2;
|
||||||
|
uint_16 langcod2e;
|
||||||
|
uint_16 langcod2;
|
||||||
|
uint_16 audprodi2e;
|
||||||
|
uint_16 mixlevel2;
|
||||||
|
uint_16 roomtyp2;
|
||||||
|
/* Copyright bit */
|
||||||
|
uint_16 copyrightb;
|
||||||
|
/* Original bit */
|
||||||
|
uint_16 origbs;
|
||||||
|
/* Timecode 1 exists */
|
||||||
|
uint_16 timecod1e;
|
||||||
|
/* Timecode 1 */
|
||||||
|
uint_16 timecod1;
|
||||||
|
/* Timecode 2 exists */
|
||||||
|
uint_16 timecod2e;
|
||||||
|
/* Timecode 2 */
|
||||||
|
uint_16 timecod2;
|
||||||
|
/* Additional bit stream info exists */
|
||||||
|
uint_16 addbsie;
|
||||||
|
/* Additional bit stream length - 1 (in bytes) */
|
||||||
|
uint_16 addbsil;
|
||||||
|
/* Additional bit stream information (max 64 bytes) */
|
||||||
|
uint_8 addbsi[64];
|
||||||
|
|
||||||
|
/* Information not in the AC-3 bitstream, but derived */
|
||||||
|
/* Number of channels (excluding LFE)
|
||||||
|
* Derived from acmod */
|
||||||
|
uint_16 nfchans;
|
||||||
|
} bsi_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* more pain */
|
||||||
|
typedef struct audblk_s
|
||||||
|
{
|
||||||
|
uint_32 magic1;
|
||||||
|
/* block switch bit indexed by channel num */
|
||||||
|
uint_16 blksw[5];
|
||||||
|
/* dither enable bit indexed by channel num */
|
||||||
|
uint_16 dithflag[5];
|
||||||
|
/* dynamic range gain exists */
|
||||||
|
uint_16 dynrnge;
|
||||||
|
/* dynamic range gain */
|
||||||
|
uint_16 dynrng;
|
||||||
|
/* if acmod==0 then */
|
||||||
|
/* dynamic range 2 gain exists */
|
||||||
|
uint_16 dynrng2e;
|
||||||
|
/* dynamic range 2 gain */
|
||||||
|
uint_16 dynrng2;
|
||||||
|
/* coupling strategy exists */
|
||||||
|
uint_16 cplstre;
|
||||||
|
/* coupling in use */
|
||||||
|
uint_16 cplinu;
|
||||||
|
/* channel coupled */
|
||||||
|
uint_16 chincpl[5];
|
||||||
|
/* if acmod==2 then */
|
||||||
|
/* Phase flags in use */
|
||||||
|
uint_16 phsflginu;
|
||||||
|
/* coupling begin frequency code */
|
||||||
|
uint_16 cplbegf;
|
||||||
|
/* coupling end frequency code */
|
||||||
|
uint_16 cplendf;
|
||||||
|
/* coupling band structure bits */
|
||||||
|
uint_16 cplbndstrc[18];
|
||||||
|
/* Do coupling co-ords exist for this channel? */
|
||||||
|
uint_16 cplcoe[5];
|
||||||
|
/* Master coupling co-ordinate */
|
||||||
|
uint_16 mstrcplco[5];
|
||||||
|
/* Per coupling band coupling co-ordinates */
|
||||||
|
uint_16 cplcoexp[5][18];
|
||||||
|
uint_16 cplcomant[5][18];
|
||||||
|
/* Phase flags for dual mono */
|
||||||
|
uint_16 phsflg[18];
|
||||||
|
/* Is there a rematrixing strategy */
|
||||||
|
uint_16 rematstr;
|
||||||
|
/* Rematrixing bits */
|
||||||
|
uint_16 rematflg[4];
|
||||||
|
/* Coupling exponent strategy */
|
||||||
|
uint_16 cplexpstr;
|
||||||
|
/* Exponent strategy for full bandwidth channels */
|
||||||
|
uint_16 chexpstr[5];
|
||||||
|
/* Exponent strategy for lfe channel */
|
||||||
|
uint_16 lfeexpstr;
|
||||||
|
/* Channel bandwidth for independent channels */
|
||||||
|
uint_16 chbwcod[5];
|
||||||
|
/* The absolute coupling exponent */
|
||||||
|
uint_16 cplabsexp;
|
||||||
|
/* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */
|
||||||
|
uint_16 cplexps[18 * 12 / 3];
|
||||||
|
/* Sanity checking constant */
|
||||||
|
uint_32 magic2;
|
||||||
|
/* fbw channel exponents */
|
||||||
|
uint_16 exps[5][252 / 3];
|
||||||
|
/* channel gain range */
|
||||||
|
uint_16 gainrng[5];
|
||||||
|
/* low frequency exponents */
|
||||||
|
uint_16 lfeexps[3];
|
||||||
|
|
||||||
|
/* Bit allocation info */
|
||||||
|
uint_16 baie;
|
||||||
|
/* Slow decay code */
|
||||||
|
uint_16 sdcycod;
|
||||||
|
/* Fast decay code */
|
||||||
|
uint_16 fdcycod;
|
||||||
|
/* Slow gain code */
|
||||||
|
uint_16 sgaincod;
|
||||||
|
/* dB per bit code */
|
||||||
|
uint_16 dbpbcod;
|
||||||
|
/* masking floor code */
|
||||||
|
uint_16 floorcod;
|
||||||
|
|
||||||
|
/* SNR offset info */
|
||||||
|
uint_16 snroffste;
|
||||||
|
/* coarse SNR offset */
|
||||||
|
uint_16 csnroffst;
|
||||||
|
/* coupling fine SNR offset */
|
||||||
|
uint_16 cplfsnroffst;
|
||||||
|
/* coupling fast gain code */
|
||||||
|
uint_16 cplfgaincod;
|
||||||
|
/* fbw fine SNR offset */
|
||||||
|
uint_16 fsnroffst[5];
|
||||||
|
/* fbw fast gain code */
|
||||||
|
uint_16 fgaincod[5];
|
||||||
|
/* lfe fine SNR offset */
|
||||||
|
uint_16 lfefsnroffst;
|
||||||
|
/* lfe fast gain code */
|
||||||
|
uint_16 lfefgaincod;
|
||||||
|
|
||||||
|
/* Coupling leak info */
|
||||||
|
uint_16 cplleake;
|
||||||
|
/* coupling fast leak initialization */
|
||||||
|
uint_16 cplfleak;
|
||||||
|
/* coupling slow leak initialization */
|
||||||
|
uint_16 cplsleak;
|
||||||
|
|
||||||
|
/* delta bit allocation info */
|
||||||
|
uint_16 deltbaie;
|
||||||
|
/* coupling delta bit allocation exists */
|
||||||
|
uint_16 cpldeltbae;
|
||||||
|
/* fbw delta bit allocation exists */
|
||||||
|
uint_16 deltbae[5];
|
||||||
|
/* number of cpl delta bit segments */
|
||||||
|
uint_16 cpldeltnseg;
|
||||||
|
/* coupling delta bit allocation offset */
|
||||||
|
uint_16 cpldeltoffst[8];
|
||||||
|
/* coupling delta bit allocation length */
|
||||||
|
uint_16 cpldeltlen[8];
|
||||||
|
/* coupling delta bit allocation length */
|
||||||
|
uint_16 cpldeltba[8];
|
||||||
|
/* number of delta bit segments */
|
||||||
|
uint_16 deltnseg[5];
|
||||||
|
/* fbw delta bit allocation offset */
|
||||||
|
uint_16 deltoffst[5][8];
|
||||||
|
/* fbw delta bit allocation length */
|
||||||
|
uint_16 deltlen[5][8];
|
||||||
|
/* fbw delta bit allocation length */
|
||||||
|
uint_16 deltba[5][8];
|
||||||
|
|
||||||
|
/* skip length exists */
|
||||||
|
uint_16 skiple;
|
||||||
|
/* skip length */
|
||||||
|
uint_16 skipl;
|
||||||
|
|
||||||
|
//Removed Feb 2000 -ah
|
||||||
|
/* channel mantissas */
|
||||||
|
//uint_16 chmant[5][256];
|
||||||
|
|
||||||
|
/* coupling mantissas */
|
||||||
|
uint_16 cplmant[256];
|
||||||
|
|
||||||
|
//Removed Feb 2000 -ah
|
||||||
|
/* coupling mantissas */
|
||||||
|
//uint_16 lfemant[7];
|
||||||
|
|
||||||
|
|
||||||
|
/* -- Information not in the bitstream, but derived thereof -- */
|
||||||
|
|
||||||
|
/* Number of coupling sub-bands */
|
||||||
|
uint_16 ncplsubnd;
|
||||||
|
|
||||||
|
/* Number of combined coupling sub-bands
|
||||||
|
* Derived from ncplsubnd and cplbndstrc */
|
||||||
|
uint_16 ncplbnd;
|
||||||
|
|
||||||
|
/* Number of exponent groups by channel
|
||||||
|
* Derived from strmant, endmant */
|
||||||
|
uint_16 nchgrps[5];
|
||||||
|
|
||||||
|
/* Number of coupling exponent groups
|
||||||
|
* Derived from cplbegf, cplendf, cplexpstr */
|
||||||
|
uint_16 ncplgrps;
|
||||||
|
|
||||||
|
/* End mantissa numbers of fbw channels */
|
||||||
|
uint_16 endmant[5];
|
||||||
|
|
||||||
|
/* Start and end mantissa numbers for the coupling channel */
|
||||||
|
uint_16 cplstrtmant;
|
||||||
|
uint_16 cplendmant;
|
||||||
|
|
||||||
|
/* Decoded exponent info */
|
||||||
|
uint_16 fbw_exp[5][256];
|
||||||
|
uint_16 cpl_exp[256];
|
||||||
|
uint_16 lfe_exp[7];
|
||||||
|
|
||||||
|
/* Bit allocation pointer results */
|
||||||
|
uint_16 fbw_bap[5][256];
|
||||||
|
uint_16 cpl_bap[256];
|
||||||
|
uint_16 lfe_bap[7];
|
||||||
|
|
||||||
|
uint_32 magic3;
|
||||||
|
} audblk_t;
|
||||||
|
|
||||||
|
|
494
ac3dec/bit_allocate.c
Normal file
494
ac3dec/bit_allocate.c
Normal file
@ -0,0 +1,494 @@
|
|||||||
|
/*
|
||||||
|
* bit_allocate.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline sint_16 logadd(sint_16 a,sint_16 b);
|
||||||
|
static sint_16 calc_lowcomp(sint_16 a,sint_16 b0,sint_16 b1,sint_16 bin);
|
||||||
|
static inline uint_16 min(sint_16 a,sint_16 b);
|
||||||
|
static inline uint_16 max(sint_16 a,sint_16 b);
|
||||||
|
static void ba_compute_psd(sint_16 start, sint_16 end, sint_16 exps[],
|
||||||
|
sint_16 psd[], sint_16 bndpsd[]);
|
||||||
|
|
||||||
|
static void ba_compute_excitation(sint_16 start, sint_16 end,sint_16 fgain,
|
||||||
|
sint_16 fastleak, sint_16 slowleak, sint_16 is_lfe, sint_16 bndpsd[],
|
||||||
|
sint_16 excite[]);
|
||||||
|
static void ba_compute_mask(sint_16 start, sint_16 end, uint_16 fscod,
|
||||||
|
uint_16 deltbae, uint_16 deltnseg, uint_16 deltoffst[], uint_16 deltba[],
|
||||||
|
uint_16 deltlen[], sint_16 excite[], sint_16 mask[]);
|
||||||
|
static void ba_compute_bap(sint_16 start, sint_16 end, sint_16 snroffset,
|
||||||
|
sint_16 psd[], sint_16 mask[], sint_16 bap[]);
|
||||||
|
|
||||||
|
/* Misc LUTs for bit allocation process */
|
||||||
|
|
||||||
|
static sint_16 slowdec[] = { 0x0f, 0x11, 0x13, 0x15 };
|
||||||
|
static sint_16 fastdec[] = { 0x3f, 0x53, 0x67, 0x7b };
|
||||||
|
static sint_16 slowgain[] = { 0x540, 0x4d8, 0x478, 0x410 };
|
||||||
|
static sint_16 dbpbtab[] = { 0x000, 0x700, 0x900, 0xb00 };
|
||||||
|
|
||||||
|
static uint_16 floortab[] = { 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800 };
|
||||||
|
static sint_16 fastgain[] = { 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400 };
|
||||||
|
|
||||||
|
|
||||||
|
static sint_16 bndtab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||||
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 31,
|
||||||
|
34, 37, 40, 43, 46, 49, 55, 61, 67, 73,
|
||||||
|
79, 85, 97, 109, 121, 133, 157, 181, 205, 229 };
|
||||||
|
|
||||||
|
static sint_16 bndsz[] = { 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, 3, 3,
|
||||||
|
3, 3, 3, 3, 3, 6, 6, 6, 6, 6,
|
||||||
|
6, 12, 12, 12, 12, 24, 24, 24, 24, 24 };
|
||||||
|
|
||||||
|
static sint_16 masktab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 29,
|
||||||
|
29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34,
|
||||||
|
34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37,
|
||||||
|
37, 37, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40,
|
||||||
|
40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
|
||||||
|
41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43,
|
||||||
|
43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44,
|
||||||
|
44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
|
||||||
|
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46,
|
||||||
|
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
|
||||||
|
46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
|
||||||
|
47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
|
||||||
|
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
|
||||||
|
48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
|
||||||
|
49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0 };
|
||||||
|
|
||||||
|
|
||||||
|
static sint_16 latab[] = { 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003b, 0x003a, 0x0039,
|
||||||
|
0x0038, 0x0037, 0x0036, 0x0035, 0x0034, 0x0034, 0x0033, 0x0032,
|
||||||
|
0x0031, 0x0030, 0x002f, 0x002f, 0x002e, 0x002d, 0x002c, 0x002c,
|
||||||
|
0x002b, 0x002a, 0x0029, 0x0029, 0x0028, 0x0027, 0x0026, 0x0026,
|
||||||
|
0x0025, 0x0024, 0x0024, 0x0023, 0x0023, 0x0022, 0x0021, 0x0021,
|
||||||
|
0x0020, 0x0020, 0x001f, 0x001e, 0x001e, 0x001d, 0x001d, 0x001c,
|
||||||
|
0x001c, 0x001b, 0x001b, 0x001a, 0x001a, 0x0019, 0x0019, 0x0018,
|
||||||
|
0x0018, 0x0017, 0x0017, 0x0016, 0x0016, 0x0015, 0x0015, 0x0015,
|
||||||
|
0x0014, 0x0014, 0x0013, 0x0013, 0x0013, 0x0012, 0x0012, 0x0012,
|
||||||
|
0x0011, 0x0011, 0x0011, 0x0010, 0x0010, 0x0010, 0x000f, 0x000f,
|
||||||
|
0x000f, 0x000e, 0x000e, 0x000e, 0x000d, 0x000d, 0x000d, 0x000d,
|
||||||
|
0x000c, 0x000c, 0x000c, 0x000c, 0x000b, 0x000b, 0x000b, 0x000b,
|
||||||
|
0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0009, 0x0009, 0x0009,
|
||||||
|
0x0009, 0x0009, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
|
||||||
|
0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0006, 0x0006,
|
||||||
|
0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0005, 0x0005,
|
||||||
|
0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0004, 0x0004,
|
||||||
|
0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
|
||||||
|
0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
|
||||||
|
0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002,
|
||||||
|
0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
|
||||||
|
0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
|
||||||
|
0x0002, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
|
||||||
|
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
|
||||||
|
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
|
||||||
|
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
|
||||||
|
0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
|
0x0000, 0x0000, 0x0000, 0x0000};
|
||||||
|
|
||||||
|
static sint_16 hth[][50] = {{ 0x04d0, 0x04d0, 0x0440, 0x0400, 0x03e0, 0x03c0, 0x03b0, 0x03b0,
|
||||||
|
0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390,
|
||||||
|
0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, 0x0350, 0x0350,
|
||||||
|
0x0340, 0x0340, 0x0330, 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0,
|
||||||
|
0x02f0, 0x02f0, 0x0300, 0x0310, 0x0340, 0x0390, 0x03e0, 0x0420,
|
||||||
|
0x0460, 0x0490, 0x04a0, 0x0460, 0x0440, 0x0440, 0x0520, 0x0800,
|
||||||
|
0x0840, 0x0840 },
|
||||||
|
|
||||||
|
{ 0x04f0, 0x04f0, 0x0460, 0x0410, 0x03e0, 0x03d0, 0x03c0, 0x03b0,
|
||||||
|
0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390,
|
||||||
|
0x0390, 0x0380, 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360,
|
||||||
|
0x0350, 0x0350, 0x0340, 0x0340, 0x0320, 0x0310, 0x0300, 0x02f0,
|
||||||
|
0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0320, 0x0350, 0x0390, 0x03e0,
|
||||||
|
0x0420, 0x0450, 0x04a0, 0x0490, 0x0460, 0x0440, 0x0480, 0x0630,
|
||||||
|
0x0840, 0x0840 },
|
||||||
|
|
||||||
|
{ 0x0580, 0x0580, 0x04b0, 0x0450, 0x0420, 0x03f0, 0x03e0, 0x03d0,
|
||||||
|
0x03c0, 0x03b0, 0x03b0, 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0,
|
||||||
|
0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, 0x0390,
|
||||||
|
0x0380, 0x0380, 0x0380, 0x0370, 0x0360, 0x0350, 0x0340, 0x0330,
|
||||||
|
0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0310,
|
||||||
|
0x0330, 0x0350, 0x03c0, 0x0410, 0x0470, 0x04a0, 0x0460, 0x0440,
|
||||||
|
0x0450, 0x04e0 }};
|
||||||
|
|
||||||
|
|
||||||
|
static sint_16 baptab[] = { 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
|
||||||
|
6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10,
|
||||||
|
10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14,
|
||||||
|
14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
|
||||||
|
|
||||||
|
static sint_16 sdecay;
|
||||||
|
static sint_16 fdecay;
|
||||||
|
static sint_16 sgain;
|
||||||
|
static sint_16 dbknee;
|
||||||
|
static sint_16 floor;
|
||||||
|
static sint_16 psd[256];
|
||||||
|
static sint_16 bndpsd[256];
|
||||||
|
static sint_16 excite[256];
|
||||||
|
static sint_16 mask[256];
|
||||||
|
|
||||||
|
static inline uint_16
|
||||||
|
max(sint_16 a,sint_16 b)
|
||||||
|
{
|
||||||
|
return (a > b ? a : b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint_16
|
||||||
|
min(sint_16 a,sint_16 b)
|
||||||
|
{
|
||||||
|
return (a < b ? a : b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline sint_16
|
||||||
|
logadd(sint_16 a,sint_16 b)
|
||||||
|
{
|
||||||
|
sint_16 c;
|
||||||
|
sint_16 address;
|
||||||
|
|
||||||
|
c = a - b;
|
||||||
|
address = min((abs(c) >> 1), 255);
|
||||||
|
|
||||||
|
if (c >= 0)
|
||||||
|
return(a + latab[address]);
|
||||||
|
else
|
||||||
|
return(b + latab[address]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bit_allocate(uint_16 fscod, bsi_t *bsi, audblk_t *audblk)
|
||||||
|
{
|
||||||
|
uint_16 i;
|
||||||
|
sint_16 fgain;
|
||||||
|
sint_16 snroffset;
|
||||||
|
sint_16 start;
|
||||||
|
sint_16 end;
|
||||||
|
sint_16 fastleak;
|
||||||
|
sint_16 slowleak;
|
||||||
|
|
||||||
|
/* Only perform bit_allocation if the exponents have changed or we
|
||||||
|
* have new sideband information */
|
||||||
|
if (audblk->chexpstr[0] == 0 && audblk->chexpstr[1] == 0 &&
|
||||||
|
audblk->chexpstr[2] == 0 && audblk->chexpstr[3] == 0 &&
|
||||||
|
audblk->chexpstr[4] == 0 && audblk->cplexpstr == 0 &&
|
||||||
|
audblk->lfeexpstr == 0 && audblk->baie == 0 &&
|
||||||
|
audblk->snroffste == 0 && audblk->deltbaie == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Do some setup before we do the bit alloc */
|
||||||
|
sdecay = slowdec[audblk->sdcycod];
|
||||||
|
fdecay = fastdec[audblk->fdcycod];
|
||||||
|
sgain = slowgain[audblk->sgaincod];
|
||||||
|
dbknee = dbpbtab[audblk->dbpbcod];
|
||||||
|
floor = floortab[audblk->floorcod];
|
||||||
|
|
||||||
|
/* if all the SNR offset constants are zero then the whole block is zero */
|
||||||
|
if(!audblk->csnroffst && !audblk->fsnroffst[0] &&
|
||||||
|
!audblk->fsnroffst[1] && !audblk->fsnroffst[2] &&
|
||||||
|
!audblk->fsnroffst[3] && !audblk->fsnroffst[4] &&
|
||||||
|
!audblk->cplfsnroffst && !audblk->lfefsnroffst)
|
||||||
|
{
|
||||||
|
memset(audblk->fbw_bap,0,sizeof(uint_16) * 256 * 5);
|
||||||
|
memset(audblk->cpl_bap,0,sizeof(uint_16) * 256);
|
||||||
|
memset(audblk->lfe_bap,0,sizeof(uint_16) * 7);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(i = 0; i < bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
start = 0;
|
||||||
|
end = audblk->endmant[i] ;
|
||||||
|
fgain = fastgain[audblk->fgaincod[i]];
|
||||||
|
snroffset = (((audblk->csnroffst - 15) << 4) + audblk->fsnroffst[i]) << 2 ;
|
||||||
|
fastleak = 0;
|
||||||
|
slowleak = 0;
|
||||||
|
|
||||||
|
ba_compute_psd(start, end, audblk->fbw_exp[i], psd, bndpsd);
|
||||||
|
|
||||||
|
ba_compute_excitation(start, end , fgain, fastleak, slowleak, 0, bndpsd, excite);
|
||||||
|
|
||||||
|
ba_compute_mask(start, end, fscod, audblk->deltbae[i], audblk->deltnseg[i],
|
||||||
|
audblk->deltoffst[i], audblk->deltba[i], audblk->deltlen[i], excite, mask);
|
||||||
|
|
||||||
|
ba_compute_bap(start, end, snroffset, psd, mask, audblk->fbw_bap[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audblk->cplinu)
|
||||||
|
{
|
||||||
|
start = audblk->cplstrtmant;
|
||||||
|
end = audblk->cplendmant;
|
||||||
|
fgain = fastgain[audblk->cplfgaincod];
|
||||||
|
snroffset = (((audblk->csnroffst - 15) << 4) + audblk->cplfsnroffst) << 2 ;
|
||||||
|
fastleak = (audblk->cplfleak << 8) + 768;
|
||||||
|
slowleak = (audblk->cplsleak << 8) + 768;
|
||||||
|
|
||||||
|
ba_compute_psd(start, end, audblk->cpl_exp, psd, bndpsd);
|
||||||
|
|
||||||
|
ba_compute_excitation(start, end , fgain, fastleak, slowleak, 0, bndpsd, excite);
|
||||||
|
|
||||||
|
ba_compute_mask(start, end, fscod, audblk->cpldeltbae, audblk->cpldeltnseg,
|
||||||
|
audblk->cpldeltoffst, audblk->cpldeltba, audblk->cpldeltlen, excite, mask);
|
||||||
|
|
||||||
|
ba_compute_bap(start, end, snroffset, psd, mask, audblk->cpl_bap);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bsi->lfeon)
|
||||||
|
{
|
||||||
|
start = 0;
|
||||||
|
end = 7;
|
||||||
|
fgain = fastgain[audblk->lfefgaincod];
|
||||||
|
snroffset = (((audblk->csnroffst - 15) << 4) + audblk->lfefsnroffst) << 2 ;
|
||||||
|
fastleak = 0;
|
||||||
|
slowleak = 0;
|
||||||
|
|
||||||
|
ba_compute_psd(start, end, audblk->lfe_exp, psd, bndpsd);
|
||||||
|
|
||||||
|
ba_compute_excitation(start, end , fgain, fastleak, slowleak, 1, bndpsd, excite);
|
||||||
|
|
||||||
|
/* Perform no delta bit allocation for lfe */
|
||||||
|
ba_compute_mask(start, end, fscod, 2, 0, 0, 0, 0, excite, mask);
|
||||||
|
|
||||||
|
ba_compute_bap(start, end, snroffset, psd, mask, audblk->lfe_bap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ba_compute_psd(sint_16 start, sint_16 end, sint_16 exps[],
|
||||||
|
sint_16 psd[], sint_16 bndpsd[])
|
||||||
|
{
|
||||||
|
int bin,i,j,k;
|
||||||
|
sint_16 lastbin = 0;
|
||||||
|
|
||||||
|
/* Map the exponents into dBs */
|
||||||
|
for (bin=start; bin<end; bin++)
|
||||||
|
{
|
||||||
|
psd[bin] = (3072 - (exps[bin] << 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Integrate the psd function over each bit allocation band */
|
||||||
|
j = start;
|
||||||
|
k = masktab[start];
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
lastbin = min(bndtab[k] + bndsz[k], end);
|
||||||
|
bndpsd[k] = psd[j];
|
||||||
|
j++;
|
||||||
|
|
||||||
|
for (i = j; i < lastbin; i++)
|
||||||
|
{
|
||||||
|
bndpsd[k] = logadd(bndpsd[k], psd[j]);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
k++;
|
||||||
|
} while (end > lastbin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ba_compute_excitation(sint_16 start, sint_16 end,sint_16 fgain,
|
||||||
|
sint_16 fastleak, sint_16 slowleak, sint_16 is_lfe, sint_16 bndpsd[],
|
||||||
|
sint_16 excite[])
|
||||||
|
{
|
||||||
|
int bin;
|
||||||
|
sint_16 bndstrt;
|
||||||
|
sint_16 bndend;
|
||||||
|
sint_16 lowcomp = 0;
|
||||||
|
sint_16 begin = 0;
|
||||||
|
|
||||||
|
/* Compute excitation function */
|
||||||
|
bndstrt = masktab[start];
|
||||||
|
bndend = masktab[end - 1] + 1;
|
||||||
|
|
||||||
|
if (bndstrt == 0) /* For fbw and lfe channels */
|
||||||
|
{
|
||||||
|
lowcomp = calc_lowcomp(lowcomp, bndpsd[0], bndpsd[1], 0);
|
||||||
|
excite[0] = bndpsd[0] - fgain - lowcomp;
|
||||||
|
lowcomp = calc_lowcomp(lowcomp, bndpsd[1], bndpsd[2], 1);
|
||||||
|
excite[1] = bndpsd[1] - fgain - lowcomp;
|
||||||
|
begin = 7 ;
|
||||||
|
|
||||||
|
/* Note: Do not call calc_lowcomp() for the last band of the lfe channel, (bin = 6) */
|
||||||
|
for (bin = 2; bin < 7; bin++)
|
||||||
|
{
|
||||||
|
if (!(is_lfe && (bin == 6)))
|
||||||
|
lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin);
|
||||||
|
fastleak = bndpsd[bin] - fgain;
|
||||||
|
slowleak = bndpsd[bin] - sgain;
|
||||||
|
excite[bin] = fastleak - lowcomp;
|
||||||
|
|
||||||
|
if (!(is_lfe && (bin == 6)))
|
||||||
|
{
|
||||||
|
if (bndpsd[bin] <= bndpsd[bin+1])
|
||||||
|
{
|
||||||
|
begin = bin + 1 ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bin = begin; bin < min(bndend, 22); bin++)
|
||||||
|
{
|
||||||
|
if (!(is_lfe && (bin == 6)))
|
||||||
|
lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin);
|
||||||
|
fastleak -= fdecay ;
|
||||||
|
fastleak = max(fastleak, bndpsd[bin] - fgain);
|
||||||
|
slowleak -= sdecay ;
|
||||||
|
slowleak = max(slowleak, bndpsd[bin] - sgain);
|
||||||
|
excite[bin] = max(fastleak - lowcomp, slowleak);
|
||||||
|
}
|
||||||
|
begin = 22;
|
||||||
|
}
|
||||||
|
else /* For coupling channel */
|
||||||
|
{
|
||||||
|
begin = bndstrt;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bin = begin; bin < bndend; bin++)
|
||||||
|
{
|
||||||
|
fastleak -= fdecay;
|
||||||
|
fastleak = max(fastleak, bndpsd[bin] - fgain);
|
||||||
|
slowleak -= sdecay;
|
||||||
|
slowleak = max(slowleak, bndpsd[bin] - sgain);
|
||||||
|
excite[bin] = max(fastleak, slowleak) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ba_compute_mask(sint_16 start, sint_16 end, uint_16 fscod,
|
||||||
|
uint_16 deltbae, uint_16 deltnseg, uint_16 deltoffst[], uint_16 deltba[],
|
||||||
|
uint_16 deltlen[], sint_16 excite[], sint_16 mask[])
|
||||||
|
{
|
||||||
|
int bin,k;
|
||||||
|
sint_16 bndstrt;
|
||||||
|
sint_16 bndend;
|
||||||
|
sint_16 delta;
|
||||||
|
|
||||||
|
bndstrt = masktab[start];
|
||||||
|
bndend = masktab[end - 1] + 1;
|
||||||
|
|
||||||
|
/* Compute the masking curve */
|
||||||
|
|
||||||
|
for (bin = bndstrt; bin < bndend; bin++)
|
||||||
|
{
|
||||||
|
if (bndpsd[bin] < dbknee)
|
||||||
|
{
|
||||||
|
excite[bin] += ((dbknee - bndpsd[bin]) >> 2);
|
||||||
|
}
|
||||||
|
mask[bin] = max(excite[bin], hth[fscod][bin]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform delta bit modulation if necessary */
|
||||||
|
if ((deltbae == DELTA_BIT_REUSE) || (deltbae == DELTA_BIT_NEW))
|
||||||
|
{
|
||||||
|
sint_16 band = 0;
|
||||||
|
sint_16 seg = 0;
|
||||||
|
|
||||||
|
for (seg = 0; seg < deltnseg+1; seg++)
|
||||||
|
{
|
||||||
|
band += deltoffst[seg];
|
||||||
|
if (deltba[seg] >= 4)
|
||||||
|
{
|
||||||
|
delta = (deltba[seg] - 3) << 7;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delta = (deltba[seg] - 4) << 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 0; k < deltlen[seg]; k++)
|
||||||
|
{
|
||||||
|
mask[band] += delta;
|
||||||
|
band++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ba_compute_bap(sint_16 start, sint_16 end, sint_16 snroffset,
|
||||||
|
sint_16 psd[], sint_16 mask[], sint_16 bap[])
|
||||||
|
{
|
||||||
|
int i,j,k;
|
||||||
|
sint_16 lastbin = 0;
|
||||||
|
sint_16 address = 0;
|
||||||
|
|
||||||
|
/* Compute the bit allocation pointer for each bin */
|
||||||
|
i = start;
|
||||||
|
j = masktab[start];
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
lastbin = min(bndtab[j] + bndsz[j], end);
|
||||||
|
mask[j] -= snroffset;
|
||||||
|
mask[j] -= floor;
|
||||||
|
|
||||||
|
if (mask[j] < 0)
|
||||||
|
mask[j] = 0;
|
||||||
|
|
||||||
|
mask[j] &= 0x1fe0;
|
||||||
|
mask[j] += floor;
|
||||||
|
for (k = i; k < lastbin; k++)
|
||||||
|
{
|
||||||
|
address = (psd[i] - mask[j]) >> 5;
|
||||||
|
address = min(63, max(0, address));
|
||||||
|
bap[i] = baptab[address];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
} while (end > lastbin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static sint_16
|
||||||
|
calc_lowcomp(sint_16 a,sint_16 b0,sint_16 b1,sint_16 bin)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (bin < 7)
|
||||||
|
{
|
||||||
|
if ((b0 + 256) == b1)
|
||||||
|
a = 384;
|
||||||
|
else if (b0 > b1)
|
||||||
|
a = max(0, a - 64);
|
||||||
|
}
|
||||||
|
else if (bin < 20)
|
||||||
|
{
|
||||||
|
if ((b0 + 256) == b1)
|
||||||
|
a = 320;
|
||||||
|
else if (b0 > b1)
|
||||||
|
a = max(0, a - 64) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
a = max(0, a - 128);
|
||||||
|
|
||||||
|
return(a);
|
||||||
|
}
|
||||||
|
|
24
ac3dec/bit_allocate.h
Normal file
24
ac3dec/bit_allocate.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* bit_allocate.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void bit_allocate(uint_16 fscod, bsi_t *bsi, audblk_t *audblk);
|
76
ac3dec/bitstream.c
Normal file
76
ac3dec/bitstream.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* bitstream.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - Dec 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free AC-3 audio decoder
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
#include "bitstream.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint_8 *buffer_start = 0;
|
||||||
|
uint_32 bits_left = 0;
|
||||||
|
uint_32 current_word;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
bitstream_fill_current()
|
||||||
|
{
|
||||||
|
current_word = *((uint_32*)buffer_start)++;
|
||||||
|
current_word = swab32(current_word);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The fast paths for _get is in the
|
||||||
|
// bitstream.h header file so it can be inlined.
|
||||||
|
//
|
||||||
|
// The "bottom half" of this routine is suffixed _bh
|
||||||
|
//
|
||||||
|
// -ah
|
||||||
|
//
|
||||||
|
|
||||||
|
uint_32
|
||||||
|
bitstream_get_bh(uint_32 num_bits)
|
||||||
|
{
|
||||||
|
uint_32 result;
|
||||||
|
|
||||||
|
num_bits -= bits_left;
|
||||||
|
result = (current_word << (32 - bits_left)) >> (32 - bits_left);
|
||||||
|
|
||||||
|
bitstream_fill_current();
|
||||||
|
|
||||||
|
if(num_bits != 0)
|
||||||
|
result = (result << num_bits) | (current_word >> (32 - num_bits));
|
||||||
|
|
||||||
|
bits_left = 32 - num_bits;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bitstream_init(uint_8 *start)
|
||||||
|
{
|
||||||
|
//initialize the start of the buffer
|
||||||
|
buffer_start = start;
|
||||||
|
bits_left = 0;
|
||||||
|
}
|
76
ac3dec/bitstream.h
Normal file
76
ac3dec/bitstream.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* bitstream.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - Dec 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free AC-3 audio decoder
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//My new and improved vego-matic endian swapping routine
|
||||||
|
//(stolen from the kernel)
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
|
||||||
|
# define swab32(x) (x)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# if defined (__i386__)
|
||||||
|
|
||||||
|
# define swab32(x) __i386_swab32(x)
|
||||||
|
static inline const uint_32 __i386_swab32(uint_32 x)
|
||||||
|
{
|
||||||
|
__asm__("bswap %0" : "=r" (x) : "0" (x));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
# define swab32(x)\
|
||||||
|
((((uint_8*)&x)[0] << 24) | (((uint_8*)&x)[1] << 16) | \
|
||||||
|
(((uint_8*)&x)[2] << 8) | (((uint_8*)&x)[3]))
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint_32 bits_left;
|
||||||
|
extern uint_32 current_word;
|
||||||
|
|
||||||
|
void bitstream_init(uint_8 *start);
|
||||||
|
|
||||||
|
uint_8 bitstream_get_byte(void);
|
||||||
|
|
||||||
|
uint_8 *bitstream_get_buffer_start(void);
|
||||||
|
void bitstream_buffer_frame(uint_32 frame_size);
|
||||||
|
|
||||||
|
uint_32 bitstream_get_bh(uint_32 num_bits);
|
||||||
|
|
||||||
|
static inline uint_32
|
||||||
|
bitstream_get(uint_32 num_bits)
|
||||||
|
{
|
||||||
|
uint_32 result;
|
||||||
|
|
||||||
|
if(num_bits < bits_left)
|
||||||
|
{
|
||||||
|
result = (current_word << (32 - bits_left)) >> (32 - num_bits);
|
||||||
|
bits_left -= num_bits;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitstream_get_bh(num_bits);
|
||||||
|
}
|
||||||
|
|
353
ac3dec/coeff.c
Normal file
353
ac3dec/coeff.c
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
/*
|
||||||
|
* coeff.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "decode.h"
|
||||||
|
#include "bitstream.h"
|
||||||
|
#include "dither.h"
|
||||||
|
#include "coeff.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
//Lookup tables of 0.15 two's complement quantization values
|
||||||
|
//
|
||||||
|
static const uint_16 q_1[3] =
|
||||||
|
{
|
||||||
|
( -2 << 15)/3, 0,( 2 << 15)/3
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint_16 q_2[5] =
|
||||||
|
{
|
||||||
|
( -4 << 15)/5,( -2 << 15)/5, 0,
|
||||||
|
( 2 << 15)/5,( 4 << 15)/5
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint_16 q_3[7] =
|
||||||
|
{
|
||||||
|
( -6 << 15)/7,( -4 << 15)/7,( -2 << 15)/7, 0,
|
||||||
|
( 2 << 15)/7,( 4 << 15)/7,( 6 << 15)/7
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint_16 q_4[11] =
|
||||||
|
{
|
||||||
|
(-10 << 15)/11,(-8 << 15)/11,(-6 << 15)/11, ( -4 << 15)/11,(-2 << 15)/11, 0,
|
||||||
|
( 2 << 15)/11,( 4 << 15)/11,( 6 << 15)/11, ( 8 << 15)/11,(10 << 15)/11
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint_16 q_5[15] =
|
||||||
|
{
|
||||||
|
(-14 << 15)/15,(-12 << 15)/15,(-10 << 15)/15,
|
||||||
|
( -8 << 15)/15,( -6 << 15)/15,( -4 << 15)/15,
|
||||||
|
( -2 << 15)/15, 0 ,( 2 << 15)/15,
|
||||||
|
( 4 << 15)/15,( 6 << 15)/15,( 8 << 15)/15,
|
||||||
|
( 10 << 15)/15,( 12 << 15)/15,( 14 << 15)/15
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Scale factors for convert_to_float
|
||||||
|
//
|
||||||
|
|
||||||
|
static const uint_32 u32_scale_factors[25] =
|
||||||
|
{
|
||||||
|
0x38000000, //2 ^ -(0 + 15)
|
||||||
|
0x37800000, //2 ^ -(1 + 15)
|
||||||
|
0x37000000, //2 ^ -(2 + 15)
|
||||||
|
0x36800000, //2 ^ -(3 + 15)
|
||||||
|
0x36000000, //2 ^ -(4 + 15)
|
||||||
|
0x35800000, //2 ^ -(5 + 15)
|
||||||
|
0x35000000, //2 ^ -(6 + 15)
|
||||||
|
0x34800000, //2 ^ -(7 + 15)
|
||||||
|
0x34000000, //2 ^ -(8 + 15)
|
||||||
|
0x33800000, //2 ^ -(9 + 15)
|
||||||
|
0x33000000, //2 ^ -(10 + 15)
|
||||||
|
0x32800000, //2 ^ -(11 + 15)
|
||||||
|
0x32000000, //2 ^ -(12 + 15)
|
||||||
|
0x31800000, //2 ^ -(13 + 15)
|
||||||
|
0x31000000, //2 ^ -(14 + 15)
|
||||||
|
0x30800000, //2 ^ -(15 + 15)
|
||||||
|
0x30000000, //2 ^ -(16 + 15)
|
||||||
|
0x2f800000, //2 ^ -(17 + 15)
|
||||||
|
0x2f000000, //2 ^ -(18 + 15)
|
||||||
|
0x2e800000, //2 ^ -(19 + 15)
|
||||||
|
0x2e000000, //2 ^ -(20 + 15)
|
||||||
|
0x2d800000, //2 ^ -(21 + 15)
|
||||||
|
0x2d000000, //2 ^ -(22 + 15)
|
||||||
|
0x2c800000, //2 ^ -(23 + 15)
|
||||||
|
0x2c000000 //2 ^ -(24 + 15)
|
||||||
|
};
|
||||||
|
|
||||||
|
static float *scale_factor = (float*)u32_scale_factors;
|
||||||
|
|
||||||
|
//These store the persistent state of the packed mantissas
|
||||||
|
static uint_16 m_1[3];
|
||||||
|
static uint_16 m_2[3];
|
||||||
|
static uint_16 m_4[2];
|
||||||
|
static uint_16 m_1_pointer;
|
||||||
|
static uint_16 m_2_pointer;
|
||||||
|
static uint_16 m_4_pointer;
|
||||||
|
|
||||||
|
//Conversion from bap to number of bits in the mantissas
|
||||||
|
//zeros account for cases 0,1,2,4 which are special cased
|
||||||
|
static uint_16 qnttztab[16] = { 0, 0, 0, 3, 0 , 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16};
|
||||||
|
|
||||||
|
static void coeff_reset(void);
|
||||||
|
static sint_16 coeff_get_mantissa(uint_16 bap, uint_16 dithflag);
|
||||||
|
static void coeff_uncouple_ch(float samples[],bsi_t *bsi,audblk_t *audblk,uint_32 ch);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert a 0.15 fixed point number into IEEE single
|
||||||
|
// precision floating point and scale by 2^-exp
|
||||||
|
//
|
||||||
|
static inline float
|
||||||
|
convert_to_float(uint_16 exp, sint_16 mantissa)
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
|
||||||
|
//the scale by 2^-15 is built into the scale factor table
|
||||||
|
x = mantissa * scale_factor[exp];
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coeff_unpack(bsi_t *bsi, audblk_t *audblk, stream_samples_t samples)
|
||||||
|
{
|
||||||
|
uint_16 i,j;
|
||||||
|
uint_32 done_cpl = 0;
|
||||||
|
sint_16 mantissa;
|
||||||
|
|
||||||
|
coeff_reset();
|
||||||
|
|
||||||
|
for(i=0; i< bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
for(j=0; j < audblk->endmant[i]; j++)
|
||||||
|
{
|
||||||
|
mantissa = coeff_get_mantissa(audblk->fbw_bap[i][j],audblk->dithflag[i]);
|
||||||
|
samples[i][j] = convert_to_float(audblk->fbw_exp[i][j],mantissa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audblk->cplinu && audblk->chincpl[i] && !(done_cpl))
|
||||||
|
{
|
||||||
|
// ncplmant is equal to 12 * ncplsubnd
|
||||||
|
// Don't dither coupling channel until channel separation so that
|
||||||
|
// interchannel noise is uncorrelated
|
||||||
|
for(j=audblk->cplstrtmant; j < audblk->cplendmant; j++)
|
||||||
|
audblk->cplmant[j] = coeff_get_mantissa(audblk->cpl_bap[j],0);
|
||||||
|
done_cpl = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//uncouple the channel if necessary
|
||||||
|
if(audblk->cplinu)
|
||||||
|
{
|
||||||
|
for(i=0; i< bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
if(audblk->chincpl[i])
|
||||||
|
coeff_uncouple_ch(samples[i],bsi,audblk,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bsi->lfeon)
|
||||||
|
{
|
||||||
|
// There are always 7 mantissas for lfe, no dither for lfe
|
||||||
|
for(j=0; j < 7 ; j++)
|
||||||
|
{
|
||||||
|
mantissa = coeff_get_mantissa(audblk->lfe_bap[j],0);
|
||||||
|
samples[5][j] = convert_to_float(audblk->lfe_exp[j],mantissa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//Fetch a mantissa from the bitstream
|
||||||
|
//
|
||||||
|
//The mantissa returned is a signed 0.15 fixed point number
|
||||||
|
//
|
||||||
|
static sint_16
|
||||||
|
coeff_get_mantissa(uint_16 bap, uint_16 dithflag)
|
||||||
|
{
|
||||||
|
uint_16 mantissa;
|
||||||
|
uint_16 group_code;
|
||||||
|
|
||||||
|
//If the bap is 0-5 then we have special cases to take care of
|
||||||
|
switch(bap)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if(dithflag)
|
||||||
|
mantissa = dither_gen();
|
||||||
|
else
|
||||||
|
mantissa = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if(m_1_pointer > 2)
|
||||||
|
{
|
||||||
|
group_code = bitstream_get(5);
|
||||||
|
|
||||||
|
if(group_code > 26)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
m_1[0] = group_code / 9;
|
||||||
|
m_1[1] = (group_code % 9) / 3;
|
||||||
|
m_1[2] = (group_code % 9) % 3;
|
||||||
|
m_1_pointer = 0;
|
||||||
|
}
|
||||||
|
mantissa = m_1[m_1_pointer++];
|
||||||
|
mantissa = q_1[mantissa];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
|
||||||
|
if(m_2_pointer > 2)
|
||||||
|
{
|
||||||
|
group_code = bitstream_get(7);
|
||||||
|
|
||||||
|
if(group_code > 124)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
m_2[0] = group_code / 25;
|
||||||
|
m_2[1] = (group_code % 25) / 5 ;
|
||||||
|
m_2[2] = (group_code % 25) % 5 ;
|
||||||
|
m_2_pointer = 0;
|
||||||
|
}
|
||||||
|
mantissa = m_2[m_2_pointer++];
|
||||||
|
mantissa = q_2[mantissa];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
mantissa = bitstream_get(3);
|
||||||
|
|
||||||
|
if(mantissa > 6)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
mantissa = q_3[mantissa];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if(m_4_pointer > 1)
|
||||||
|
{
|
||||||
|
group_code = bitstream_get(7);
|
||||||
|
|
||||||
|
if(group_code > 120)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
m_4[0] = group_code / 11;
|
||||||
|
m_4[1] = group_code % 11;
|
||||||
|
m_4_pointer = 0;
|
||||||
|
}
|
||||||
|
mantissa = m_4[m_4_pointer++];
|
||||||
|
mantissa = q_4[mantissa];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
mantissa = bitstream_get(4);
|
||||||
|
|
||||||
|
if(mantissa > 14)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
mantissa = q_5[mantissa];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mantissa = bitstream_get(qnttztab[bap]);
|
||||||
|
mantissa <<= 16 - qnttztab[bap];
|
||||||
|
}
|
||||||
|
|
||||||
|
return mantissa;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
error:
|
||||||
|
if(!error_flag)
|
||||||
|
fprintf(stderr,"** Invalid mantissa - skipping frame **\n");
|
||||||
|
error_flag = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reset the mantissa state
|
||||||
|
//
|
||||||
|
static void
|
||||||
|
coeff_reset(void)
|
||||||
|
{
|
||||||
|
m_1[2] = m_1[1] = m_1[0] = 0;
|
||||||
|
m_2[2] = m_2[1] = m_2[0] = 0;
|
||||||
|
m_4[1] = m_4[0] = 0;
|
||||||
|
m_1_pointer = m_2_pointer = m_4_pointer = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Uncouple the coupling channel into a fbw channel
|
||||||
|
//
|
||||||
|
static void
|
||||||
|
coeff_uncouple_ch(float samples[],bsi_t *bsi,audblk_t *audblk,uint_32 ch)
|
||||||
|
{
|
||||||
|
uint_32 bnd = 0;
|
||||||
|
uint_32 sub_bnd = 0;
|
||||||
|
uint_32 i,j;
|
||||||
|
float cpl_coord = 1.0;
|
||||||
|
uint_32 cpl_exp_tmp;
|
||||||
|
uint_32 cpl_mant_tmp;
|
||||||
|
sint_16 mantissa;
|
||||||
|
|
||||||
|
|
||||||
|
for(i=audblk->cplstrtmant;i<audblk->cplendmant;)
|
||||||
|
{
|
||||||
|
if(!audblk->cplbndstrc[sub_bnd++])
|
||||||
|
{
|
||||||
|
cpl_exp_tmp = audblk->cplcoexp[ch][bnd] + 3 * audblk->mstrcplco[ch];
|
||||||
|
if(audblk->cplcoexp[ch][bnd] == 15)
|
||||||
|
cpl_mant_tmp = (audblk->cplcomant[ch][bnd]) << 11;
|
||||||
|
else
|
||||||
|
cpl_mant_tmp = ((0x10) | audblk->cplcomant[ch][bnd]) << 10;
|
||||||
|
|
||||||
|
cpl_coord = convert_to_float(cpl_exp_tmp,cpl_mant_tmp) * 8.0f;
|
||||||
|
|
||||||
|
//Invert the phase for the right channel if necessary
|
||||||
|
if(bsi->acmod == 0x2 && audblk->phsflginu && ch == 1 && audblk->phsflg[bnd])
|
||||||
|
cpl_coord *= -1;
|
||||||
|
|
||||||
|
bnd++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(j=0;j < 12; j++)
|
||||||
|
{
|
||||||
|
//Get new dither values for each channel if necessary, so
|
||||||
|
//the channels are uncorrelated
|
||||||
|
if(audblk->dithflag[ch] && audblk->cpl_bap[i] == 0)
|
||||||
|
mantissa = dither_gen();
|
||||||
|
else
|
||||||
|
mantissa = audblk->cplmant[i];
|
||||||
|
|
||||||
|
samples[i] = cpl_coord * convert_to_float(audblk->cpl_exp[i],mantissa);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
ac3dec/coeff.h
Normal file
24
ac3dec/coeff.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* coeff.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - Feb 2000
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void coeff_unpack(bsi_t *bsi, audblk_t *audblk,stream_samples_t samples);
|
96
ac3dec/crc.c
Normal file
96
ac3dec/crc.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* crc.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "crc.h"
|
||||||
|
|
||||||
|
static const uint_16 crc_lut[256] =
|
||||||
|
{
|
||||||
|
0x0000,0x8005,0x800f,0x000a,0x801b,0x001e,0x0014,0x8011,
|
||||||
|
0x8033,0x0036,0x003c,0x8039,0x0028,0x802d,0x8027,0x0022,
|
||||||
|
0x8063,0x0066,0x006c,0x8069,0x0078,0x807d,0x8077,0x0072,
|
||||||
|
0x0050,0x8055,0x805f,0x005a,0x804b,0x004e,0x0044,0x8041,
|
||||||
|
0x80c3,0x00c6,0x00cc,0x80c9,0x00d8,0x80dd,0x80d7,0x00d2,
|
||||||
|
0x00f0,0x80f5,0x80ff,0x00fa,0x80eb,0x00ee,0x00e4,0x80e1,
|
||||||
|
0x00a0,0x80a5,0x80af,0x00aa,0x80bb,0x00be,0x00b4,0x80b1,
|
||||||
|
0x8093,0x0096,0x009c,0x8099,0x0088,0x808d,0x8087,0x0082,
|
||||||
|
0x8183,0x0186,0x018c,0x8189,0x0198,0x819d,0x8197,0x0192,
|
||||||
|
0x01b0,0x81b5,0x81bf,0x01ba,0x81ab,0x01ae,0x01a4,0x81a1,
|
||||||
|
0x01e0,0x81e5,0x81ef,0x01ea,0x81fb,0x01fe,0x01f4,0x81f1,
|
||||||
|
0x81d3,0x01d6,0x01dc,0x81d9,0x01c8,0x81cd,0x81c7,0x01c2,
|
||||||
|
0x0140,0x8145,0x814f,0x014a,0x815b,0x015e,0x0154,0x8151,
|
||||||
|
0x8173,0x0176,0x017c,0x8179,0x0168,0x816d,0x8167,0x0162,
|
||||||
|
0x8123,0x0126,0x012c,0x8129,0x0138,0x813d,0x8137,0x0132,
|
||||||
|
0x0110,0x8115,0x811f,0x011a,0x810b,0x010e,0x0104,0x8101,
|
||||||
|
0x8303,0x0306,0x030c,0x8309,0x0318,0x831d,0x8317,0x0312,
|
||||||
|
0x0330,0x8335,0x833f,0x033a,0x832b,0x032e,0x0324,0x8321,
|
||||||
|
0x0360,0x8365,0x836f,0x036a,0x837b,0x037e,0x0374,0x8371,
|
||||||
|
0x8353,0x0356,0x035c,0x8359,0x0348,0x834d,0x8347,0x0342,
|
||||||
|
0x03c0,0x83c5,0x83cf,0x03ca,0x83db,0x03de,0x03d4,0x83d1,
|
||||||
|
0x83f3,0x03f6,0x03fc,0x83f9,0x03e8,0x83ed,0x83e7,0x03e2,
|
||||||
|
0x83a3,0x03a6,0x03ac,0x83a9,0x03b8,0x83bd,0x83b7,0x03b2,
|
||||||
|
0x0390,0x8395,0x839f,0x039a,0x838b,0x038e,0x0384,0x8381,
|
||||||
|
0x0280,0x8285,0x828f,0x028a,0x829b,0x029e,0x0294,0x8291,
|
||||||
|
0x82b3,0x02b6,0x02bc,0x82b9,0x02a8,0x82ad,0x82a7,0x02a2,
|
||||||
|
0x82e3,0x02e6,0x02ec,0x82e9,0x02f8,0x82fd,0x82f7,0x02f2,
|
||||||
|
0x02d0,0x82d5,0x82df,0x02da,0x82cb,0x02ce,0x02c4,0x82c1,
|
||||||
|
0x8243,0x0246,0x024c,0x8249,0x0258,0x825d,0x8257,0x0252,
|
||||||
|
0x0270,0x8275,0x827f,0x027a,0x826b,0x026e,0x0264,0x8261,
|
||||||
|
0x0220,0x8225,0x822f,0x022a,0x823b,0x023e,0x0234,0x8231,
|
||||||
|
0x8213,0x0216,0x021c,0x8219,0x0208,0x820d,0x8207,0x0202
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint_16 state;
|
||||||
|
|
||||||
|
void
|
||||||
|
crc_init(void)
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void crc_process_byte(uint_8 data)
|
||||||
|
{
|
||||||
|
state = crc_lut[data ^ (state>>8)] ^ (state<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
crc_process_frame(uint_8 *data,uint_32 num_bytes)
|
||||||
|
{
|
||||||
|
uint_32 i;
|
||||||
|
|
||||||
|
for(i=0;i<num_bytes;i++)
|
||||||
|
crc_process_byte(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crc_validate(void)
|
||||||
|
{
|
||||||
|
return(state == 0);
|
||||||
|
}
|
27
ac3dec/crc.h
Normal file
27
ac3dec/crc.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* crc.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int crc_validate(void);
|
||||||
|
void crc_init(void);
|
||||||
|
void crc_process_byte(uint_8 data);
|
||||||
|
void crc_process_frame(uint_8 *data,uint_32 num_bytes);
|
58
ac3dec/debug.c
Normal file
58
ac3dec/debug.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* debug.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
static int debug_level = -1;
|
||||||
|
|
||||||
|
// Determine is debug output is required.
|
||||||
|
// We could potentially have multiple levels of debug info
|
||||||
|
int debug_is_on(void)
|
||||||
|
{
|
||||||
|
char *env_var;
|
||||||
|
|
||||||
|
if(debug_level < 0)
|
||||||
|
{
|
||||||
|
env_var = getenv("AC3_DEBUG");
|
||||||
|
|
||||||
|
if (env_var)
|
||||||
|
{
|
||||||
|
debug_level = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
debug_level = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return debug_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If you don't have gcc, then ya don't get debug output
|
||||||
|
#ifndef __GNUC__
|
||||||
|
void dprintf(char fmt[],...)
|
||||||
|
{
|
||||||
|
int foo = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
37
ac3dec/debug.h
Normal file
37
ac3dec/debug.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* debug.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int debug_is_on(void);
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define dprintf(format,args...)\
|
||||||
|
{\
|
||||||
|
if (debug_is_on())\
|
||||||
|
{\
|
||||||
|
fprintf(stderr,format,## args);\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void dprintf(char fmt[],...);
|
||||||
|
#endif
|
269
ac3dec/decode.c
Normal file
269
ac3dec/decode.c
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
/*
|
||||||
|
* decode.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* Added support for DVB-s PCI card by:
|
||||||
|
* Matjaz Thaler <matjaz.thaler@rd.iskraemeco.si> - November 2000
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
#include "bitstream.h"
|
||||||
|
#include "imdct.h"
|
||||||
|
#include "exponent.h"
|
||||||
|
#include "coeff.h"
|
||||||
|
#include "bit_allocate.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "crc.h"
|
||||||
|
#include "stats.h"
|
||||||
|
#include "rematrix.h"
|
||||||
|
#include "sanity_check.h"
|
||||||
|
#include "downmix.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define AC3_BUFFER_SIZE (6*1024*16)
|
||||||
|
|
||||||
|
//our global config structure
|
||||||
|
ac3_config_t ac3_config;
|
||||||
|
uint_32 error_flag = 0;
|
||||||
|
|
||||||
|
static audblk_t audblk;
|
||||||
|
static bsi_t bsi;
|
||||||
|
static syncinfo_t syncinfo;
|
||||||
|
static uint_32 frame_count = 0;
|
||||||
|
//static uint_32 is_output_initialized = 0;
|
||||||
|
|
||||||
|
//the floating point samples for one audblk
|
||||||
|
static stream_samples_t samples;
|
||||||
|
|
||||||
|
//the integer samples for the entire frame (with enough space for 2 ch out)
|
||||||
|
//if this size change, be sure to change the size when muting
|
||||||
|
static sint_16 s16_samples[2 * 6 * 256];
|
||||||
|
|
||||||
|
|
||||||
|
//Storage for the syncframe
|
||||||
|
#define SYNC_BUFFER_MAX_SIZE 4096
|
||||||
|
static uint_8 sync_buffer[SYNC_BUFFER_MAX_SIZE];
|
||||||
|
static uint_32 sync_buffer_size = 0;;
|
||||||
|
|
||||||
|
uint_32
|
||||||
|
decode_sync_buffer_syncframe(syncinfo_t *syncinfo, uint_8 **start,uint_8 *end)
|
||||||
|
{
|
||||||
|
uint_8 *cur = *start;
|
||||||
|
uint_16 syncword = syncinfo->syncword;
|
||||||
|
uint_32 ret = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find an ac3 sync frame.
|
||||||
|
//
|
||||||
|
resync:
|
||||||
|
|
||||||
|
while(syncword != 0x0b77)
|
||||||
|
{
|
||||||
|
if(cur >= end)
|
||||||
|
goto done;
|
||||||
|
syncword = (syncword << 8) + *cur++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//need the next 3 bytes to decide how big the frame is
|
||||||
|
while(sync_buffer_size < 3)
|
||||||
|
{
|
||||||
|
if(cur >= end)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
sync_buffer[sync_buffer_size++] = *cur++;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_syncinfo(syncinfo,sync_buffer);
|
||||||
|
stats_print_syncinfo(syncinfo);
|
||||||
|
|
||||||
|
while(sync_buffer_size < syncinfo->frame_size * 2 - 2)
|
||||||
|
{
|
||||||
|
if(cur >= end)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
sync_buffer[sync_buffer_size++] = *cur++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the crc over the entire frame
|
||||||
|
crc_init();
|
||||||
|
crc_process_frame(sync_buffer,syncinfo->frame_size * 2 - 2);
|
||||||
|
|
||||||
|
if(!crc_validate())
|
||||||
|
{
|
||||||
|
fprintf(stderr,"** CRC failed - skipping frame **\n");
|
||||||
|
syncword = 0xffff;
|
||||||
|
sync_buffer_size = 0;
|
||||||
|
goto resync;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//if we got to this point, we found a valid ac3 frame to decode
|
||||||
|
//
|
||||||
|
|
||||||
|
bitstream_init(sync_buffer);
|
||||||
|
//get rid of the syncinfo struct as we already parsed it
|
||||||
|
bitstream_get(24);
|
||||||
|
|
||||||
|
//reset the syncword for next time
|
||||||
|
syncword = 0xffff;
|
||||||
|
sync_buffer_size = 0;
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
done:
|
||||||
|
syncinfo->syncword = syncword;
|
||||||
|
*start = cur;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
decode_mute(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"muting frame\n");
|
||||||
|
//mute the frame
|
||||||
|
memset(s16_samples,0,sizeof(sint_16) * 256 * 2 * 6);
|
||||||
|
error_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ac3_init(ac3_config_t *config)
|
||||||
|
{
|
||||||
|
memcpy(&ac3_config,config,sizeof(ac3_config_t));
|
||||||
|
|
||||||
|
imdct_init();
|
||||||
|
sanity_check_init(&syncinfo,&bsi,&audblk);
|
||||||
|
|
||||||
|
// ac3_output = *foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint_32 ac3_decode_data(uint_8 *data_start,uint_8 *data_end, int ac3reset, int *input_pointer, int *output_pointer, char *ac3_data)
|
||||||
|
{
|
||||||
|
uint_32 i;
|
||||||
|
int datasize;
|
||||||
|
char *data;
|
||||||
|
|
||||||
|
if(ac3reset != 0){
|
||||||
|
syncinfo.syncword = 0xffff;
|
||||||
|
sync_buffer_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(decode_sync_buffer_syncframe(&syncinfo,&data_start,data_end))
|
||||||
|
{
|
||||||
|
dprintf("(decode) begin frame %d\n",frame_count++);
|
||||||
|
|
||||||
|
if(error_flag)
|
||||||
|
{
|
||||||
|
decode_mute();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_bsi(&bsi);
|
||||||
|
|
||||||
|
for(i=0; i < 6; i++)
|
||||||
|
{
|
||||||
|
//Initialize freq/time sample storage
|
||||||
|
memset(samples,0,sizeof(float) * 256 * (bsi.nfchans + bsi.lfeon));
|
||||||
|
|
||||||
|
// Extract most of the audblk info from the bitstream
|
||||||
|
// (minus the mantissas
|
||||||
|
parse_audblk(&bsi,&audblk);
|
||||||
|
|
||||||
|
// Take the differential exponent data and turn it into
|
||||||
|
// absolute exponents
|
||||||
|
exponent_unpack(&bsi,&audblk);
|
||||||
|
if(error_flag)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
// Figure out how many bits per mantissa
|
||||||
|
bit_allocate(syncinfo.fscod,&bsi,&audblk);
|
||||||
|
|
||||||
|
// Extract the mantissas from the stream and
|
||||||
|
// generate floating point frequency coefficients
|
||||||
|
coeff_unpack(&bsi,&audblk,samples);
|
||||||
|
if(error_flag)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if(bsi.acmod == 0x2)
|
||||||
|
rematrix(&audblk,samples);
|
||||||
|
|
||||||
|
// Convert the frequency samples into time samples
|
||||||
|
imdct(&bsi,&audblk,samples);
|
||||||
|
|
||||||
|
// Downmix into the requested number of channels
|
||||||
|
// and convert floating point to sint_16
|
||||||
|
downmix(&bsi,samples,&s16_samples[i * 2 * 256]);
|
||||||
|
|
||||||
|
sanity_check(&syncinfo,&bsi,&audblk);
|
||||||
|
if(error_flag)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_auxdata(&syncinfo);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(!is_output_initialized)
|
||||||
|
{
|
||||||
|
ac3_output.open(16,syncinfo.sampling_rate,2);
|
||||||
|
is_output_initialized = 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
data = (char *)s16_samples;
|
||||||
|
datasize = 0;
|
||||||
|
while(datasize < 6144){
|
||||||
|
if(((*input_pointer+1) % AC3_BUFFER_SIZE) != *output_pointer){ // There is room in the sync_buffer
|
||||||
|
ac3_data[*input_pointer]=data[datasize];
|
||||||
|
datasize++;
|
||||||
|
*input_pointer = (*input_pointer+1) % AC3_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
*input_pointer = *output_pointer = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//write(1, s16_samples, 256 * 6 * 2* 2);
|
||||||
|
//ac3_output.play(s16_samples, 256 * 6 * 2);
|
||||||
|
error:
|
||||||
|
;
|
||||||
|
//find a new frame
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
22
ac3dec/decode.h
Normal file
22
ac3dec/decode.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* decode.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
115
ac3dec/dither.c
Normal file
115
ac3dec/dither.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* dither.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "dither.h"
|
||||||
|
|
||||||
|
|
||||||
|
const uint_16 dither_lut[256] =
|
||||||
|
{
|
||||||
|
0x0000, 0xa011, 0xe033, 0x4022, 0x6077, 0xc066, 0x8044, 0x2055,
|
||||||
|
0xc0ee, 0x60ff, 0x20dd, 0x80cc, 0xa099, 0x0088, 0x40aa, 0xe0bb,
|
||||||
|
0x21cd, 0x81dc, 0xc1fe, 0x61ef, 0x41ba, 0xe1ab, 0xa189, 0x0198,
|
||||||
|
0xe123, 0x4132, 0x0110, 0xa101, 0x8154, 0x2145, 0x6167, 0xc176,
|
||||||
|
0x439a, 0xe38b, 0xa3a9, 0x03b8, 0x23ed, 0x83fc, 0xc3de, 0x63cf,
|
||||||
|
0x8374, 0x2365, 0x6347, 0xc356, 0xe303, 0x4312, 0x0330, 0xa321,
|
||||||
|
0x6257, 0xc246, 0x8264, 0x2275, 0x0220, 0xa231, 0xe213, 0x4202,
|
||||||
|
0xa2b9, 0x02a8, 0x428a, 0xe29b, 0xc2ce, 0x62df, 0x22fd, 0x82ec,
|
||||||
|
0x8734, 0x2725, 0x6707, 0xc716, 0xe743, 0x4752, 0x0770, 0xa761,
|
||||||
|
0x47da, 0xe7cb, 0xa7e9, 0x07f8, 0x27ad, 0x87bc, 0xc79e, 0x678f,
|
||||||
|
0xa6f9, 0x06e8, 0x46ca, 0xe6db, 0xc68e, 0x669f, 0x26bd, 0x86ac,
|
||||||
|
0x6617, 0xc606, 0x8624, 0x2635, 0x0660, 0xa671, 0xe653, 0x4642,
|
||||||
|
0xc4ae, 0x64bf, 0x249d, 0x848c, 0xa4d9, 0x04c8, 0x44ea, 0xe4fb,
|
||||||
|
0x0440, 0xa451, 0xe473, 0x4462, 0x6437, 0xc426, 0x8404, 0x2415,
|
||||||
|
0xe563, 0x4572, 0x0550, 0xa541, 0x8514, 0x2505, 0x6527, 0xc536,
|
||||||
|
0x258d, 0x859c, 0xc5be, 0x65af, 0x45fa, 0xe5eb, 0xa5c9, 0x05d8,
|
||||||
|
0xae79, 0x0e68, 0x4e4a, 0xee5b, 0xce0e, 0x6e1f, 0x2e3d, 0x8e2c,
|
||||||
|
0x6e97, 0xce86, 0x8ea4, 0x2eb5, 0x0ee0, 0xaef1, 0xeed3, 0x4ec2,
|
||||||
|
0x8fb4, 0x2fa5, 0x6f87, 0xcf96, 0xefc3, 0x4fd2, 0x0ff0, 0xafe1,
|
||||||
|
0x4f5a, 0xef4b, 0xaf69, 0x0f78, 0x2f2d, 0x8f3c, 0xcf1e, 0x6f0f,
|
||||||
|
0xede3, 0x4df2, 0x0dd0, 0xadc1, 0x8d94, 0x2d85, 0x6da7, 0xcdb6,
|
||||||
|
0x2d0d, 0x8d1c, 0xcd3e, 0x6d2f, 0x4d7a, 0xed6b, 0xad49, 0x0d58,
|
||||||
|
0xcc2e, 0x6c3f, 0x2c1d, 0x8c0c, 0xac59, 0x0c48, 0x4c6a, 0xec7b,
|
||||||
|
0x0cc0, 0xacd1, 0xecf3, 0x4ce2, 0x6cb7, 0xcca6, 0x8c84, 0x2c95,
|
||||||
|
0x294d, 0x895c, 0xc97e, 0x696f, 0x493a, 0xe92b, 0xa909, 0x0918,
|
||||||
|
0xe9a3, 0x49b2, 0x0990, 0xa981, 0x89d4, 0x29c5, 0x69e7, 0xc9f6,
|
||||||
|
0x0880, 0xa891, 0xe8b3, 0x48a2, 0x68f7, 0xc8e6, 0x88c4, 0x28d5,
|
||||||
|
0xc86e, 0x687f, 0x285d, 0x884c, 0xa819, 0x0808, 0x482a, 0xe83b,
|
||||||
|
0x6ad7, 0xcac6, 0x8ae4, 0x2af5, 0x0aa0, 0xaab1, 0xea93, 0x4a82,
|
||||||
|
0xaa39, 0x0a28, 0x4a0a, 0xea1b, 0xca4e, 0x6a5f, 0x2a7d, 0x8a6c,
|
||||||
|
0x4b1a, 0xeb0b, 0xab29, 0x0b38, 0x2b6d, 0x8b7c, 0xcb5e, 0x6b4f,
|
||||||
|
0x8bf4, 0x2be5, 0x6bc7, 0xcbd6, 0xeb83, 0x4b92, 0x0bb0, 0xaba1
|
||||||
|
};
|
||||||
|
|
||||||
|
uint_16 lfsr_state = 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// see dither_gen (inline-able) in dither.h
|
||||||
|
//
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
//
|
||||||
|
// this is the old dither_gen with is much slower than the new inlined
|
||||||
|
// lut version and is still here because it's easier to understand.
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate eight bits of pseudo-entropy using a 16 bit linear
|
||||||
|
* feedback shift register (LFSR). The primitive polynomial used
|
||||||
|
* is 1 + x^4 + x^14 + x^16.
|
||||||
|
*
|
||||||
|
* The distribution is uniform, over the range [-0.707,0.707]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint_16 dither_gen(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint_32 state;
|
||||||
|
|
||||||
|
//explicitly bring the state into a local var as gcc > 3.0?
|
||||||
|
//doesn't know how to optimize out the stores
|
||||||
|
state = lfsr_state;
|
||||||
|
|
||||||
|
//Generate eight pseudo random bits
|
||||||
|
for(i=0;i<8;i++)
|
||||||
|
{
|
||||||
|
state <<= 1;
|
||||||
|
|
||||||
|
if(state & 0x10000)
|
||||||
|
state ^= 0xa011;
|
||||||
|
}
|
||||||
|
|
||||||
|
lfsr_state = state;
|
||||||
|
|
||||||
|
return (((((sint_32)state<<8)>>8) * (sint_32) (0.707106 * 256.0))>>16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
37
ac3dec/dither.h
Normal file
37
ac3dec/dither.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* dither.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern uint_16 lfsr_state;
|
||||||
|
extern const uint_16 dither_lut[256];
|
||||||
|
|
||||||
|
static inline uint_16 dither_gen(void)
|
||||||
|
{
|
||||||
|
sint_16 state;
|
||||||
|
|
||||||
|
state = dither_lut[lfsr_state >> 8] ^ (lfsr_state << 8);
|
||||||
|
|
||||||
|
lfsr_state = (uint_16) state;
|
||||||
|
|
||||||
|
return ((state * (sint_32) (0.707106 * 256.0))>>8);
|
||||||
|
}
|
428
ac3dec/downmix.c
Normal file
428
ac3dec/downmix.c
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* downmix.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - Sept 1999
|
||||||
|
*
|
||||||
|
* Originally based on code by Yuqing Deng.
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "decode.h"
|
||||||
|
#include "downmix.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
//Pre-scaled downmix coefficients
|
||||||
|
static float cmixlev_lut[4] = { 0.2928, 0.2468, 0.2071, 0.2468 };
|
||||||
|
static float smixlev_lut[4] = { 0.2928, 0.2071, 0.0 , 0.2071 };
|
||||||
|
|
||||||
|
static void
|
||||||
|
downmix_3f_2r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||||
|
{
|
||||||
|
uint_32 j;
|
||||||
|
float right_tmp;
|
||||||
|
float left_tmp;
|
||||||
|
float clev,slev;
|
||||||
|
float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
|
||||||
|
|
||||||
|
left = samples[0];
|
||||||
|
centre = samples[1];
|
||||||
|
right = samples[2];
|
||||||
|
left_sur = samples[3];
|
||||||
|
right_sur = samples[4];
|
||||||
|
|
||||||
|
clev = cmixlev_lut[bsi->cmixlev];
|
||||||
|
slev = smixlev_lut[bsi->surmixlev];
|
||||||
|
|
||||||
|
#if defined DOLBY_SURROUND
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
right_tmp = *left_sur++ + *right_sur++;
|
||||||
|
left_tmp = 1.4142f * *left++ + *centre - right_tmp;
|
||||||
|
right_tmp += 1.4142f * *right++ + *centre++;
|
||||||
|
|
||||||
|
s16_samples[j * 2 ] = (sint_16) (left_tmp * 16000.0f);
|
||||||
|
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 16000.0f);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
left_tmp = 0.4142f * *left++ + clev * *centre + slev * *left_sur++;
|
||||||
|
right_tmp= 0.4142f * *right++ + clev * *centre++ + slev * *right_sur++;
|
||||||
|
|
||||||
|
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||||
|
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
downmix_2f_2r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||||
|
{
|
||||||
|
uint_32 j;
|
||||||
|
float right_tmp;
|
||||||
|
float left_tmp;
|
||||||
|
float slev;
|
||||||
|
float *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
|
||||||
|
|
||||||
|
left = samples[0];
|
||||||
|
right = samples[1];
|
||||||
|
left_sur = samples[2];
|
||||||
|
right_sur = samples[3];
|
||||||
|
|
||||||
|
slev = smixlev_lut[bsi->surmixlev];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
left_tmp = 0.4142f * *left++ + slev * *left_sur++;
|
||||||
|
right_tmp= 0.4142f * *right++ + slev * *right_sur++;
|
||||||
|
|
||||||
|
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||||
|
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
downmix_3f_1r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||||
|
{
|
||||||
|
uint_32 j;
|
||||||
|
float right_tmp;
|
||||||
|
float left_tmp;
|
||||||
|
float clev,slev;
|
||||||
|
float *centre = 0, *left = 0, *right = 0, *sur = 0;
|
||||||
|
|
||||||
|
left = samples[0];
|
||||||
|
centre = samples[1];
|
||||||
|
right = samples[2];
|
||||||
|
//Mono surround
|
||||||
|
sur = samples[3];
|
||||||
|
|
||||||
|
clev = cmixlev_lut[bsi->cmixlev];
|
||||||
|
slev = smixlev_lut[bsi->surmixlev];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
left_tmp = 0.4142f * *left++ + clev * *centre++ + slev * *sur;
|
||||||
|
right_tmp= 0.4142f * *right++ + clev * *centre + slev * *sur++;
|
||||||
|
|
||||||
|
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||||
|
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
downmix_2f_1r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||||
|
{
|
||||||
|
uint_32 j;
|
||||||
|
float right_tmp;
|
||||||
|
float left_tmp;
|
||||||
|
float slev;
|
||||||
|
float *left = 0, *right = 0, *sur = 0;
|
||||||
|
|
||||||
|
left = samples[0];
|
||||||
|
right = samples[1];
|
||||||
|
//Mono surround
|
||||||
|
sur = samples[2];
|
||||||
|
|
||||||
|
slev = smixlev_lut[bsi->surmixlev];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
left_tmp = 0.4142f * *left++ + slev * *sur;
|
||||||
|
right_tmp= 0.4142f * *right++ + slev * *sur++;
|
||||||
|
|
||||||
|
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||||
|
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
downmix_3f_0r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||||
|
{
|
||||||
|
uint_32 j;
|
||||||
|
float right_tmp;
|
||||||
|
float left_tmp;
|
||||||
|
float clev;
|
||||||
|
float *centre = 0, *left = 0, *right = 0;
|
||||||
|
|
||||||
|
left = samples[0];
|
||||||
|
centre = samples[1];
|
||||||
|
right = samples[2];
|
||||||
|
|
||||||
|
clev = cmixlev_lut[bsi->cmixlev];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
left_tmp = 0.4142f * *left++ + clev * *centre;
|
||||||
|
right_tmp= 0.4142f * *right++ + clev * *centre++;
|
||||||
|
|
||||||
|
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||||
|
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
downmix_2f_0r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||||
|
{
|
||||||
|
uint_32 j;
|
||||||
|
float *left = 0, *right = 0;
|
||||||
|
|
||||||
|
left = samples[0];
|
||||||
|
right = samples[1];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
s16_samples[j * 2 ] = (sint_16) (*left++ * 32767.0f);
|
||||||
|
s16_samples[j * 2 + 1] = (sint_16) (*right++ * 32767.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
downmix_1f_0r_to_2ch(float *centre,sint_16 *s16_samples)
|
||||||
|
{
|
||||||
|
uint_32 j;
|
||||||
|
float tmp;
|
||||||
|
|
||||||
|
//Mono program!
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
tmp = 32767.0f * 0.7071f * *centre++;
|
||||||
|
|
||||||
|
s16_samples[j * 2 ] = s16_samples[j * 2 + 1] = (sint_16) tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Downmix into 2 or 4 channels (4 ch isn't in quite yet)
|
||||||
|
//
|
||||||
|
// The downmix function names have the following format
|
||||||
|
//
|
||||||
|
// downmix_Xf_Yr_to_[2|4]ch[_dolby]
|
||||||
|
//
|
||||||
|
// where X = number of front channels
|
||||||
|
// Y = number of rear channels
|
||||||
|
// [2|4] = number of output channels
|
||||||
|
// [_dolby] = with or without dolby surround mix
|
||||||
|
//
|
||||||
|
|
||||||
|
void downmix(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||||
|
{
|
||||||
|
if(bsi->acmod > 7)
|
||||||
|
dprintf("(downmix) invalid acmod number\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
//There are two main cases, with or without Dolby Surround
|
||||||
|
//
|
||||||
|
if(ac3_config.flags & AC3_DOLBY_SURR_ENABLE)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Dolby Surround Mixes not currently enabled\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Non-Dolby surround downmixes
|
||||||
|
switch(bsi->acmod)
|
||||||
|
{
|
||||||
|
// 3/2
|
||||||
|
case 7:
|
||||||
|
downmix_3f_2r_to_2ch(bsi,samples,s16_samples);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 2/2
|
||||||
|
case 6:
|
||||||
|
downmix_2f_2r_to_2ch(bsi,samples,s16_samples);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 3/1
|
||||||
|
case 5:
|
||||||
|
downmix_3f_1r_to_2ch(bsi,samples,s16_samples);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 2/1
|
||||||
|
case 4:
|
||||||
|
downmix_2f_1r_to_2ch(bsi,samples,s16_samples);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 3/0
|
||||||
|
case 3:
|
||||||
|
downmix_3f_0r_to_2ch(bsi,samples,s16_samples);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
downmix_2f_0r_to_2ch(bsi,samples,s16_samples);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 1/0
|
||||||
|
case 1:
|
||||||
|
downmix_1f_0r_to_2ch(samples[0],s16_samples);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 1+1
|
||||||
|
case 0:
|
||||||
|
downmix_1f_0r_to_2ch(samples[ac3_config.dual_mono_ch_sel],s16_samples);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
//the dolby mixes lay here for the time being
|
||||||
|
switch(bsi->acmod)
|
||||||
|
{
|
||||||
|
// 3/2
|
||||||
|
case 7:
|
||||||
|
left = samples[0];
|
||||||
|
centre = samples[1];
|
||||||
|
right = samples[2];
|
||||||
|
left_sur = samples[3];
|
||||||
|
right_sur = samples[4];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++;
|
||||||
|
left_tmp = -1 * right_tmp;
|
||||||
|
right_tmp += 0.3204f * *right++ + 0.2265f * *centre;
|
||||||
|
left_tmp += 0.3204f * *left++ + 0.2265f * *centre++;
|
||||||
|
|
||||||
|
samples[1][j] = right_tmp;
|
||||||
|
samples[0][j] = left_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 2/2
|
||||||
|
case 6:
|
||||||
|
left = samples[0];
|
||||||
|
right = samples[1];
|
||||||
|
left_sur = samples[2];
|
||||||
|
right_sur = samples[3];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++;
|
||||||
|
left_tmp = -1 * right_tmp;
|
||||||
|
right_tmp += 0.3204f * *right++;
|
||||||
|
left_tmp += 0.3204f * *left++ ;
|
||||||
|
|
||||||
|
samples[1][j] = right_tmp;
|
||||||
|
samples[0][j] = left_tmp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 3/1
|
||||||
|
case 5:
|
||||||
|
left = samples[0];
|
||||||
|
centre = samples[1];
|
||||||
|
right = samples[2];
|
||||||
|
//Mono surround
|
||||||
|
right_sur = samples[3];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
right_tmp = 0.2265f * *right_sur++;
|
||||||
|
left_tmp = -1 * right_tmp;
|
||||||
|
right_tmp += 0.3204f * *right++ + 0.2265f * *centre;
|
||||||
|
left_tmp += 0.3204f * *left++ + 0.2265f * *centre++;
|
||||||
|
|
||||||
|
samples[1][j] = right_tmp;
|
||||||
|
samples[0][j] = left_tmp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 2/1
|
||||||
|
case 4:
|
||||||
|
left = samples[0];
|
||||||
|
right = samples[1];
|
||||||
|
//Mono surround
|
||||||
|
right_sur = samples[2];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
right_tmp = 0.2265f * *right_sur++;
|
||||||
|
left_tmp = -1 * right_tmp;
|
||||||
|
right_tmp += 0.3204f * *right++;
|
||||||
|
left_tmp += 0.3204f * *left++;
|
||||||
|
|
||||||
|
samples[1][j] = right_tmp;
|
||||||
|
samples[0][j] = left_tmp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 3/0
|
||||||
|
case 3:
|
||||||
|
left = samples[0];
|
||||||
|
centre = samples[1];
|
||||||
|
right = samples[2];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
right_tmp = 0.3204f * *right++ + 0.2265f * *centre;
|
||||||
|
left_tmp = 0.3204f * *left++ + 0.2265f * *centre++;
|
||||||
|
|
||||||
|
samples[1][j] = right_tmp;
|
||||||
|
samples[0][j] = left_tmp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 2/0
|
||||||
|
case 2:
|
||||||
|
//Do nothing!
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 1/0
|
||||||
|
case 1:
|
||||||
|
//Mono program!
|
||||||
|
right = samples[0];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
right_tmp = 0.7071f * *right++;
|
||||||
|
|
||||||
|
samples[1][j] = right_tmp;
|
||||||
|
samples[0][j] = right_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 1+1
|
||||||
|
case 0:
|
||||||
|
//Dual mono, output selected by user
|
||||||
|
right = samples[ac3_config.dual_mono_ch_sel];
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
right_tmp = 0.7071f * *right++;
|
||||||
|
|
||||||
|
samples[1][j] = right_tmp;
|
||||||
|
samples[0][j] = right_tmp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
28
ac3dec/downmix.h
Normal file
28
ac3dec/downmix.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* downmix.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - Sept 1999
|
||||||
|
*
|
||||||
|
* Originally based on code by Yeqing Deng.
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void downmix(bsi_t* bsi, stream_samples_t stream_samples,sint_16 *s16_samples);
|
135
ac3dec/exponent.c
Normal file
135
ac3dec/exponent.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* exponent.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "decode.h"
|
||||||
|
#include "exponent.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void exp_unpack_ch(uint_16 type,uint_16 expstr,uint_16 ngrps,uint_16 initial_exp,
|
||||||
|
uint_16 exps[], uint_16 *dest);
|
||||||
|
|
||||||
|
void
|
||||||
|
exponent_unpack( bsi_t *bsi, audblk_t *audblk)
|
||||||
|
{
|
||||||
|
uint_16 i;
|
||||||
|
|
||||||
|
for(i=0; i< bsi->nfchans; i++)
|
||||||
|
exp_unpack_ch(UNPACK_FBW, audblk->chexpstr[i], audblk->nchgrps[i], audblk->exps[i][0],
|
||||||
|
&audblk->exps[i][1], audblk->fbw_exp[i]);
|
||||||
|
|
||||||
|
if(audblk->cplinu)
|
||||||
|
exp_unpack_ch(UNPACK_CPL, audblk->cplexpstr, audblk->ncplgrps, audblk->cplabsexp << 1,
|
||||||
|
audblk->cplexps, &audblk->cpl_exp[audblk->cplstrtmant]);
|
||||||
|
|
||||||
|
if(bsi->lfeon)
|
||||||
|
exp_unpack_ch(UNPACK_LFE, audblk->lfeexpstr, 2, audblk->lfeexps[0],
|
||||||
|
&audblk->lfeexps[1], audblk->lfe_exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
exp_unpack_ch(uint_16 type,uint_16 expstr,uint_16 ngrps,uint_16 initial_exp,
|
||||||
|
uint_16 exps[], uint_16 *dest)
|
||||||
|
{
|
||||||
|
uint_16 i,j;
|
||||||
|
sint_16 exp_acc;
|
||||||
|
sint_16 exp_1,exp_2,exp_3;
|
||||||
|
|
||||||
|
if(expstr == EXP_REUSE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Handle the initial absolute exponent */
|
||||||
|
exp_acc = initial_exp;
|
||||||
|
j = 0;
|
||||||
|
|
||||||
|
/* In the case of a fbw channel then the initial absolute values is
|
||||||
|
* also an exponent */
|
||||||
|
if(type != UNPACK_CPL)
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
|
||||||
|
/* Loop through the groups and fill the dest array appropriately */
|
||||||
|
for(i=0; i< ngrps; i++)
|
||||||
|
{
|
||||||
|
if(exps[i] > 124)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
exp_1 = exps[i] / 25;
|
||||||
|
exp_2 = (exps[i] - (exp_1 * 25)) / 5;
|
||||||
|
exp_3 = exps[i] - (exp_1 * 25) - (exp_2 * 5) ;
|
||||||
|
|
||||||
|
exp_acc += (exp_1 - 2);
|
||||||
|
|
||||||
|
switch(expstr)
|
||||||
|
{
|
||||||
|
case EXP_D45:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
case EXP_D25:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
case EXP_D15:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
exp_acc += (exp_2 - 2);
|
||||||
|
|
||||||
|
switch(expstr)
|
||||||
|
{
|
||||||
|
case EXP_D45:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
case EXP_D25:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
case EXP_D15:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
exp_acc += (exp_3 - 2);
|
||||||
|
|
||||||
|
switch(expstr)
|
||||||
|
{
|
||||||
|
case EXP_D45:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
case EXP_D25:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
case EXP_D15:
|
||||||
|
dest[j++] = exp_acc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
goto error;
|
||||||
|
error:
|
||||||
|
if(!error_flag)
|
||||||
|
fprintf(stderr,"** Invalid exponent - skipping frame **\n");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
28
ac3dec/exponent.h
Normal file
28
ac3dec/exponent.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* exponent.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define UNPACK_FBW 1
|
||||||
|
#define UNPACK_CPL 2
|
||||||
|
#define UNPACK_LFE 4
|
||||||
|
|
||||||
|
void exponent_unpack( bsi_t *bsi, audblk_t *audblk);
|
468
ac3dec/imdct.c
Normal file
468
ac3dec/imdct.c
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
/*
|
||||||
|
* imdct.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "decode.h"
|
||||||
|
#include "imdct.h"
|
||||||
|
|
||||||
|
void imdct_do_256(float data[],float delay[]);
|
||||||
|
void imdct_do_512(float data[],float delay[]);
|
||||||
|
|
||||||
|
typedef struct complex_s
|
||||||
|
{
|
||||||
|
float real;
|
||||||
|
float imag;
|
||||||
|
} complex_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define N 512
|
||||||
|
|
||||||
|
|
||||||
|
/* 128 point bit-reverse LUT */
|
||||||
|
static uint_8 bit_reverse_512[128] = {
|
||||||
|
0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70,
|
||||||
|
0x08, 0x48, 0x28, 0x68, 0x18, 0x58, 0x38, 0x78,
|
||||||
|
0x04, 0x44, 0x24, 0x64, 0x14, 0x54, 0x34, 0x74,
|
||||||
|
0x0c, 0x4c, 0x2c, 0x6c, 0x1c, 0x5c, 0x3c, 0x7c,
|
||||||
|
0x02, 0x42, 0x22, 0x62, 0x12, 0x52, 0x32, 0x72,
|
||||||
|
0x0a, 0x4a, 0x2a, 0x6a, 0x1a, 0x5a, 0x3a, 0x7a,
|
||||||
|
0x06, 0x46, 0x26, 0x66, 0x16, 0x56, 0x36, 0x76,
|
||||||
|
0x0e, 0x4e, 0x2e, 0x6e, 0x1e, 0x5e, 0x3e, 0x7e,
|
||||||
|
0x01, 0x41, 0x21, 0x61, 0x11, 0x51, 0x31, 0x71,
|
||||||
|
0x09, 0x49, 0x29, 0x69, 0x19, 0x59, 0x39, 0x79,
|
||||||
|
0x05, 0x45, 0x25, 0x65, 0x15, 0x55, 0x35, 0x75,
|
||||||
|
0x0d, 0x4d, 0x2d, 0x6d, 0x1d, 0x5d, 0x3d, 0x7d,
|
||||||
|
0x03, 0x43, 0x23, 0x63, 0x13, 0x53, 0x33, 0x73,
|
||||||
|
0x0b, 0x4b, 0x2b, 0x6b, 0x1b, 0x5b, 0x3b, 0x7b,
|
||||||
|
0x07, 0x47, 0x27, 0x67, 0x17, 0x57, 0x37, 0x77,
|
||||||
|
0x0f, 0x4f, 0x2f, 0x6f, 0x1f, 0x5f, 0x3f, 0x7f};
|
||||||
|
|
||||||
|
static uint_8 bit_reverse_256[64] = {
|
||||||
|
0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38,
|
||||||
|
0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c,
|
||||||
|
0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a,
|
||||||
|
0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e,
|
||||||
|
0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39,
|
||||||
|
0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d,
|
||||||
|
0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b,
|
||||||
|
0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f};
|
||||||
|
|
||||||
|
static complex_t buf[128];
|
||||||
|
|
||||||
|
/* Twiddle factor LUT */
|
||||||
|
static complex_t *w[7];
|
||||||
|
static complex_t w_1[1];
|
||||||
|
static complex_t w_2[2];
|
||||||
|
static complex_t w_4[4];
|
||||||
|
static complex_t w_8[8];
|
||||||
|
static complex_t w_16[16];
|
||||||
|
static complex_t w_32[32];
|
||||||
|
static complex_t w_64[64];
|
||||||
|
|
||||||
|
/* Twiddle factors for IMDCT */
|
||||||
|
static float xcos1[128];
|
||||||
|
static float xsin1[128];
|
||||||
|
static float xcos2[64];
|
||||||
|
static float xsin2[64];
|
||||||
|
|
||||||
|
/* Delay buffer for time domain interleaving */
|
||||||
|
static float delay[6][256];
|
||||||
|
|
||||||
|
/* Windowing function for Modified DCT - Thank you acroread */
|
||||||
|
static float window[] = {
|
||||||
|
0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130,
|
||||||
|
0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443,
|
||||||
|
0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061,
|
||||||
|
0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121,
|
||||||
|
0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770,
|
||||||
|
0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153,
|
||||||
|
0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389,
|
||||||
|
0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563,
|
||||||
|
0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699,
|
||||||
|
0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757,
|
||||||
|
0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626,
|
||||||
|
0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126,
|
||||||
|
0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019,
|
||||||
|
0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031,
|
||||||
|
0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873,
|
||||||
|
0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269,
|
||||||
|
0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981,
|
||||||
|
0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831,
|
||||||
|
0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716,
|
||||||
|
0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610,
|
||||||
|
0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560,
|
||||||
|
0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674,
|
||||||
|
0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099,
|
||||||
|
0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994,
|
||||||
|
0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513,
|
||||||
|
0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788,
|
||||||
|
0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919,
|
||||||
|
0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974,
|
||||||
|
0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993,
|
||||||
|
0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999,
|
||||||
|
0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000,
|
||||||
|
1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000 };
|
||||||
|
|
||||||
|
|
||||||
|
static inline void swap_cmplx(complex_t *a, complex_t *b)
|
||||||
|
{
|
||||||
|
complex_t tmp;
|
||||||
|
|
||||||
|
tmp = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline complex_t cmplx_mult(complex_t a, complex_t b)
|
||||||
|
{
|
||||||
|
complex_t ret;
|
||||||
|
|
||||||
|
ret.real = a.real * b.real - a.imag * b.imag;
|
||||||
|
ret.imag = a.real * b.imag + a.imag * b.real;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void imdct_init(void)
|
||||||
|
{
|
||||||
|
int i,k;
|
||||||
|
complex_t angle_step;
|
||||||
|
complex_t current_angle;
|
||||||
|
|
||||||
|
/* Twiddle factors to turn IFFT into IMDCT */
|
||||||
|
for( i=0; i < 128; i++)
|
||||||
|
{
|
||||||
|
xcos1[i] = -cos(2.0f * M_PI * (8*i+1)/(8*N)) ;
|
||||||
|
xsin1[i] = -sin(2.0f * M_PI * (8*i+1)/(8*N)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* More twiddle factors to turn IFFT into IMDCT */
|
||||||
|
for( i=0; i < 64; i++)
|
||||||
|
{
|
||||||
|
xcos2[i] = -cos(2.0f * M_PI * (8*i+1)/(4*N)) ;
|
||||||
|
xsin2[i] = -sin(2.0f * M_PI * (8*i+1)/(4*N)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Canonical twiddle factors for FFT */
|
||||||
|
w[0] = w_1;
|
||||||
|
w[1] = w_2;
|
||||||
|
w[2] = w_4;
|
||||||
|
w[3] = w_8;
|
||||||
|
w[4] = w_16;
|
||||||
|
w[5] = w_32;
|
||||||
|
w[6] = w_64;
|
||||||
|
|
||||||
|
for( i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
angle_step.real = cos(-2.0 * M_PI / (1 << (i+1)));
|
||||||
|
angle_step.imag = sin(-2.0 * M_PI / (1 << (i+1)));
|
||||||
|
|
||||||
|
current_angle.real = 1.0;
|
||||||
|
current_angle.imag = 0.0;
|
||||||
|
|
||||||
|
for (k = 0; k < 1 << i; k++)
|
||||||
|
{
|
||||||
|
w[i][k] = current_angle;
|
||||||
|
current_angle = cmplx_mult(current_angle,angle_step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
imdct_do_512(float data[],float delay[])
|
||||||
|
{
|
||||||
|
int i,k;
|
||||||
|
int p,q;
|
||||||
|
int m;
|
||||||
|
int two_m;
|
||||||
|
int two_m_plus_one;
|
||||||
|
|
||||||
|
float tmp_a_i;
|
||||||
|
float tmp_a_r;
|
||||||
|
float tmp_b_i;
|
||||||
|
float tmp_b_r;
|
||||||
|
|
||||||
|
float *data_ptr;
|
||||||
|
float *delay_ptr;
|
||||||
|
float *window_ptr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 512 IMDCT with source and dest data in 'data'
|
||||||
|
//
|
||||||
|
|
||||||
|
// Pre IFFT complex multiply plus IFFT cmplx conjugate and bit reverse
|
||||||
|
// permutation
|
||||||
|
for( i=0; i < 128; i++)
|
||||||
|
{
|
||||||
|
k = bit_reverse_512[i];
|
||||||
|
|
||||||
|
/* z[i] = (X[256-2*i-1] + j * X[2*i]) * (xcos1[i] + j * xsin1[i]) ; */
|
||||||
|
buf[k].real = (data[256-2*i-1] * xcos1[i]) - (data[2*i] * xsin1[i]);
|
||||||
|
buf[k].imag = -1.0 * ((data[2*i] * xcos1[i]) + (data[256-2*i-1] * xsin1[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FFT Merge
|
||||||
|
for (m=0; m < 7; m++)
|
||||||
|
{
|
||||||
|
if(m)
|
||||||
|
two_m = (1 << m);
|
||||||
|
else
|
||||||
|
two_m = 1;
|
||||||
|
|
||||||
|
two_m_plus_one = (1 << (m+1));
|
||||||
|
|
||||||
|
for(k = 0; k < two_m; k++)
|
||||||
|
{
|
||||||
|
for(i = 0; i < 128; i += two_m_plus_one)
|
||||||
|
{
|
||||||
|
p = k + i;
|
||||||
|
q = p + two_m;
|
||||||
|
tmp_a_r = buf[p].real;
|
||||||
|
tmp_a_i = buf[p].imag;
|
||||||
|
tmp_b_r = buf[q].real * w[m][k].real - buf[q].imag * w[m][k].imag;
|
||||||
|
tmp_b_i = buf[q].imag * w[m][k].real + buf[q].real * w[m][k].imag;
|
||||||
|
buf[p].real = tmp_a_r + tmp_b_r;
|
||||||
|
buf[p].imag = tmp_a_i + tmp_b_i;
|
||||||
|
buf[q].real = tmp_a_r - tmp_b_r;
|
||||||
|
buf[q].imag = tmp_a_i - tmp_b_i;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Post IFFT complex multiply plus IFFT complex conjugate*/
|
||||||
|
for( i=0; i < 128; i++)
|
||||||
|
{
|
||||||
|
/* y[n] = z[n] * (xcos1[n] + j * xsin1[n]) ; */
|
||||||
|
tmp_a_r = buf[i].real;
|
||||||
|
tmp_a_i = buf[i].imag;
|
||||||
|
//Note that I flipped the signs on the imaginary ops to do the complex conj
|
||||||
|
buf[i].real =(tmp_a_r * xcos1[i]) + (tmp_a_i * xsin1[i]);
|
||||||
|
buf[i].imag =(tmp_a_r * xsin1[i]) - (tmp_a_i * xcos1[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_ptr = data;
|
||||||
|
delay_ptr = delay;
|
||||||
|
window_ptr = window;
|
||||||
|
|
||||||
|
/* Window and convert to real valued signal */
|
||||||
|
for(i=0; i< 64; i++)
|
||||||
|
{
|
||||||
|
*data_ptr++ = 2.0f * (-buf[64+i].imag * *window_ptr++ + *delay_ptr++);
|
||||||
|
*data_ptr++ = 2.0f * ( buf[64-i-1].real * *window_ptr++ + *delay_ptr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i< 64; i++)
|
||||||
|
{
|
||||||
|
*data_ptr++ = 2.0f * (-buf[i].real * *window_ptr++ + *delay_ptr++);
|
||||||
|
*data_ptr++ = 2.0f * ( buf[128-i-1].imag * *window_ptr++ + *delay_ptr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The trailing edge of the window goes into the delay line */
|
||||||
|
delay_ptr = delay;
|
||||||
|
|
||||||
|
for(i=0; i< 64; i++)
|
||||||
|
{
|
||||||
|
*delay_ptr++ = -buf[64+i].real * *--window_ptr;
|
||||||
|
*delay_ptr++ = buf[64-i-1].imag * *--window_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<64; i++)
|
||||||
|
{
|
||||||
|
*delay_ptr++ = buf[i].imag * *--window_ptr;
|
||||||
|
*delay_ptr++ = -buf[128-i-1].real * *--window_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
imdct_do_256(float data[],float delay[])
|
||||||
|
{
|
||||||
|
int i,k;
|
||||||
|
int p,q;
|
||||||
|
int m;
|
||||||
|
int two_m;
|
||||||
|
int two_m_plus_one;
|
||||||
|
|
||||||
|
float tmp_a_i;
|
||||||
|
float tmp_a_r;
|
||||||
|
float tmp_b_i;
|
||||||
|
float tmp_b_r;
|
||||||
|
|
||||||
|
float *data_ptr;
|
||||||
|
float *delay_ptr;
|
||||||
|
float *window_ptr;
|
||||||
|
|
||||||
|
complex_t *buf_1, *buf_2;
|
||||||
|
|
||||||
|
buf_1 = &buf[0];
|
||||||
|
buf_2 = &buf[64];
|
||||||
|
|
||||||
|
// Pre IFFT complex multiply plus IFFT cmplx conjugate and bit reverse
|
||||||
|
// permutation
|
||||||
|
for(i=0; i<64; i++)
|
||||||
|
{
|
||||||
|
/* X1[i] = X[2*i] */
|
||||||
|
/* X2[i] = X[2*i+1] */
|
||||||
|
|
||||||
|
k = bit_reverse_256[i];
|
||||||
|
|
||||||
|
p = 2 * (128-2*i-1);
|
||||||
|
q = 2 * (2 * i);
|
||||||
|
|
||||||
|
/* Z1[i] = (X1[128-2*i-1] + j * X1[2*i]) * (xcos2[i] + j * xsin2[i]); */
|
||||||
|
buf_1[k].real = data[p] * xcos2[i] - data[q] * xsin2[i];
|
||||||
|
buf_1[k].imag = -1.0f * (data[q] * xcos2[i] + data[p] * xsin2[i]);
|
||||||
|
/* Z2[i] = (X2[128-2*i-1] + j * X2[2*i]) * (xcos2[i] + j * xsin2[i]); */
|
||||||
|
buf_2[k].real = data[p + 1] * xcos2[i] - data[q + 1] * xsin2[i];
|
||||||
|
buf_2[k].imag = -1.0f * ( data[q + 1] * xcos2[i] + data[p + 1] * xsin2[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FFT Merge
|
||||||
|
for (m=0; m < 6; m++)
|
||||||
|
{
|
||||||
|
two_m = (1 << m);
|
||||||
|
two_m_plus_one = (1 << (m+1));
|
||||||
|
|
||||||
|
if(m)
|
||||||
|
two_m = (1 << m);
|
||||||
|
else
|
||||||
|
two_m = 1;
|
||||||
|
|
||||||
|
for(k = 0; k < two_m; k++)
|
||||||
|
{
|
||||||
|
for(i = 0; i < 64; i += two_m_plus_one)
|
||||||
|
{
|
||||||
|
p = k + i;
|
||||||
|
q = p + two_m;
|
||||||
|
//Do block 1
|
||||||
|
tmp_a_r = buf_1[p].real;
|
||||||
|
tmp_a_i = buf_1[p].imag;
|
||||||
|
tmp_b_r = buf_1[q].real * w[m][k].real - buf_1[q].imag * w[m][k].imag;
|
||||||
|
tmp_b_i = buf_1[q].imag * w[m][k].real + buf_1[q].real * w[m][k].imag;
|
||||||
|
buf_1[p].real = tmp_a_r + tmp_b_r;
|
||||||
|
buf_1[p].imag = tmp_a_i + tmp_b_i;
|
||||||
|
buf_1[q].real = tmp_a_r - tmp_b_r;
|
||||||
|
buf_1[q].imag = tmp_a_i - tmp_b_i;
|
||||||
|
|
||||||
|
//Do block 2
|
||||||
|
tmp_a_r = buf_2[p].real;
|
||||||
|
tmp_a_i = buf_2[p].imag;
|
||||||
|
tmp_b_r = buf_2[q].real * w[m][k].real - buf_2[q].imag * w[m][k].imag;
|
||||||
|
tmp_b_i = buf_2[q].imag * w[m][k].real + buf_2[q].real * w[m][k].imag;
|
||||||
|
buf_2[p].real = tmp_a_r + tmp_b_r;
|
||||||
|
buf_2[p].imag = tmp_a_i + tmp_b_i;
|
||||||
|
buf_2[q].real = tmp_a_r - tmp_b_r;
|
||||||
|
buf_2[q].imag = tmp_a_i - tmp_b_i;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post IFFT complex multiply
|
||||||
|
for( i=0; i < 64; i++)
|
||||||
|
{
|
||||||
|
//Note that I flipped the signs on the imaginary ops to do the complex conj
|
||||||
|
|
||||||
|
/* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */
|
||||||
|
tmp_a_r = buf_1[i].real;
|
||||||
|
tmp_a_i = buf_1[i].imag;
|
||||||
|
buf_1[i].real =(tmp_a_r * xcos2[i]) + (tmp_a_i * xsin2[i]);
|
||||||
|
buf_1[i].imag =(tmp_a_r * xsin2[i]) - (tmp_a_i * xcos2[i]);
|
||||||
|
/* y2[n] = z2[n] * (xcos2[n] + j * xsin2[n]) ; */
|
||||||
|
tmp_a_r = buf_2[i].real;
|
||||||
|
tmp_a_i = buf_2[i].imag;
|
||||||
|
buf_2[i].real =(tmp_a_r * xcos2[i]) + (tmp_a_i * xsin2[i]);
|
||||||
|
buf_2[i].imag =(tmp_a_r * xsin2[i]) - (tmp_a_i * xcos2[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_ptr = data;
|
||||||
|
delay_ptr = delay;
|
||||||
|
window_ptr = window;
|
||||||
|
|
||||||
|
/* Window and convert to real valued signal */
|
||||||
|
for(i=0; i< 64; i++)
|
||||||
|
{
|
||||||
|
*data_ptr++ = 2.0f * (-buf_1[i].imag * *window_ptr++ + *delay_ptr++);
|
||||||
|
*data_ptr++ = 2.0f * ( buf_1[64-i-1].real * *window_ptr++ + *delay_ptr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i< 64; i++)
|
||||||
|
{
|
||||||
|
*data_ptr++ = 2.0f * (-buf_1[i].real * *window_ptr++ + *delay_ptr++);
|
||||||
|
*data_ptr++ = 2.0f * ( buf_1[64-i-1].imag * *window_ptr++ + *delay_ptr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay_ptr = delay;
|
||||||
|
|
||||||
|
for(i=0; i< 64; i++)
|
||||||
|
{
|
||||||
|
*delay_ptr++ = -buf_2[i].real * *--window_ptr;
|
||||||
|
*delay_ptr++ = buf_2[64-i-1].imag * *--window_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i< 64; i++)
|
||||||
|
{
|
||||||
|
*delay_ptr++ = buf_2[i].imag * *--window_ptr;
|
||||||
|
*delay_ptr++ = -buf_2[64-i-1].real * *--window_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME remove - for timing code
|
||||||
|
///#include <sys/time.h>
|
||||||
|
//FIXME remove
|
||||||
|
|
||||||
|
void
|
||||||
|
imdct(bsi_t *bsi,audblk_t *audblk, stream_samples_t samples) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
//handy timing code
|
||||||
|
//struct timeval start,end;
|
||||||
|
|
||||||
|
//gettimeofday(&start,0);
|
||||||
|
|
||||||
|
for(i=0; i<bsi->nfchans;i++)
|
||||||
|
{
|
||||||
|
if(audblk->blksw[i])
|
||||||
|
imdct_do_256(samples[i],delay[i]);
|
||||||
|
else
|
||||||
|
imdct_do_512(samples[i],delay[i]);
|
||||||
|
}
|
||||||
|
//gettimeofday(&end,0);
|
||||||
|
//printf("imdct %ld us\n",(end.tv_sec - start.tv_sec) * 1000000 +
|
||||||
|
//end.tv_usec - start.tv_usec);
|
||||||
|
|
||||||
|
//XXX We don't bother with the IMDCT for the LFE as it's currently
|
||||||
|
//unused.
|
||||||
|
//if (bsi->lfeon)
|
||||||
|
// imdct_do_512(coeffs->lfe,samples->channel[5],delay[5]);
|
||||||
|
//
|
||||||
|
}
|
26
ac3dec/imdct.h
Normal file
26
ac3dec/imdct.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* imdct.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void imdct(bsi_t *bsi,audblk_t *audblk, stream_samples_t samples);
|
||||||
|
void imdct_init(void);
|
597
ac3dec/parse.c
Normal file
597
ac3dec/parse.c
Normal file
@ -0,0 +1,597 @@
|
|||||||
|
/*
|
||||||
|
* parse.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "bitstream.h"
|
||||||
|
#include "stats.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
|
/* Misc LUT */
|
||||||
|
static const uint_16 nfchans[8] = {2,1,2,3,3,4,4,5};
|
||||||
|
|
||||||
|
struct frmsize_s
|
||||||
|
{
|
||||||
|
uint_16 bit_rate;
|
||||||
|
uint_16 frm_size[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct frmsize_s frmsizecod_tbl[64] =
|
||||||
|
{
|
||||||
|
{ 32 ,{64 ,69 ,96 } },
|
||||||
|
{ 32 ,{64 ,70 ,96 } },
|
||||||
|
{ 40 ,{80 ,87 ,120 } },
|
||||||
|
{ 40 ,{80 ,88 ,120 } },
|
||||||
|
{ 48 ,{96 ,104 ,144 } },
|
||||||
|
{ 48 ,{96 ,105 ,144 } },
|
||||||
|
{ 56 ,{112 ,121 ,168 } },
|
||||||
|
{ 56 ,{112 ,122 ,168 } },
|
||||||
|
{ 64 ,{128 ,139 ,192 } },
|
||||||
|
{ 64 ,{128 ,140 ,192 } },
|
||||||
|
{ 80 ,{160 ,174 ,240 } },
|
||||||
|
{ 80 ,{160 ,175 ,240 } },
|
||||||
|
{ 96 ,{192 ,208 ,288 } },
|
||||||
|
{ 96 ,{192 ,209 ,288 } },
|
||||||
|
{ 112 ,{224 ,243 ,336 } },
|
||||||
|
{ 112 ,{224 ,244 ,336 } },
|
||||||
|
{ 128 ,{256 ,278 ,384 } },
|
||||||
|
{ 128 ,{256 ,279 ,384 } },
|
||||||
|
{ 160 ,{320 ,348 ,480 } },
|
||||||
|
{ 160 ,{320 ,349 ,480 } },
|
||||||
|
{ 192 ,{384 ,417 ,576 } },
|
||||||
|
{ 192 ,{384 ,418 ,576 } },
|
||||||
|
{ 224 ,{448 ,487 ,672 } },
|
||||||
|
{ 224 ,{448 ,488 ,672 } },
|
||||||
|
{ 256 ,{512 ,557 ,768 } },
|
||||||
|
{ 256 ,{512 ,558 ,768 } },
|
||||||
|
{ 320 ,{640 ,696 ,960 } },
|
||||||
|
{ 320 ,{640 ,697 ,960 } },
|
||||||
|
{ 384 ,{768 ,835 ,1152 } },
|
||||||
|
{ 384 ,{768 ,836 ,1152 } },
|
||||||
|
{ 448 ,{896 ,975 ,1344 } },
|
||||||
|
{ 448 ,{896 ,976 ,1344 } },
|
||||||
|
{ 512 ,{1024 ,1114 ,1536 } },
|
||||||
|
{ 512 ,{1024 ,1115 ,1536 } },
|
||||||
|
{ 576 ,{1152 ,1253 ,1728 } },
|
||||||
|
{ 576 ,{1152 ,1254 ,1728 } },
|
||||||
|
{ 640 ,{1280 ,1393 ,1920 } },
|
||||||
|
{ 640 ,{1280 ,1394 ,1920 } }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Parse a syncinfo structure, minus the sync word */
|
||||||
|
void
|
||||||
|
parse_syncinfo(syncinfo_t *syncinfo,uint_8 *data)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// We need to read in the entire syncinfo struct (0x0b77 + 24 bits)
|
||||||
|
// in order to determine how big the frame is
|
||||||
|
//
|
||||||
|
|
||||||
|
// Get the sampling rate
|
||||||
|
syncinfo->fscod = (data[2] >> 6) & 0x3;
|
||||||
|
|
||||||
|
if(syncinfo->fscod == 3)
|
||||||
|
{
|
||||||
|
//invalid sampling rate code
|
||||||
|
error_flag = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(syncinfo->fscod == 2)
|
||||||
|
syncinfo->sampling_rate = 32000;
|
||||||
|
else if(syncinfo->fscod == 1)
|
||||||
|
syncinfo->sampling_rate = 44100;
|
||||||
|
else
|
||||||
|
syncinfo->sampling_rate = 48000;
|
||||||
|
|
||||||
|
// Get the frame size code
|
||||||
|
syncinfo->frmsizecod = data[2] & 0x3f;
|
||||||
|
|
||||||
|
// Calculate the frame size and bitrate
|
||||||
|
syncinfo->frame_size =
|
||||||
|
frmsizecod_tbl[syncinfo->frmsizecod].frm_size[syncinfo->fscod];
|
||||||
|
syncinfo->bit_rate = frmsizecod_tbl[syncinfo->frmsizecod].bit_rate;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine fills a bsi struct from the AC3 stream
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
parse_bsi(bsi_t *bsi)
|
||||||
|
{
|
||||||
|
uint_32 i;
|
||||||
|
|
||||||
|
/* Check the AC-3 version number */
|
||||||
|
bsi->bsid = bitstream_get(5);
|
||||||
|
|
||||||
|
/* Get the audio service provided by the steram */
|
||||||
|
bsi->bsmod = bitstream_get(3);
|
||||||
|
|
||||||
|
/* Get the audio coding mode (ie how many channels)*/
|
||||||
|
bsi->acmod = bitstream_get(3);
|
||||||
|
/* Predecode the number of full bandwidth channels as we use this
|
||||||
|
* number a lot */
|
||||||
|
bsi->nfchans = nfchans[bsi->acmod];
|
||||||
|
|
||||||
|
/* If it is in use, get the centre channel mix level */
|
||||||
|
if ((bsi->acmod & 0x1) && (bsi->acmod != 0x1))
|
||||||
|
bsi->cmixlev = bitstream_get(2);
|
||||||
|
|
||||||
|
/* If it is in use, get the surround channel mix level */
|
||||||
|
if (bsi->acmod & 0x4)
|
||||||
|
bsi->surmixlev = bitstream_get(2);
|
||||||
|
|
||||||
|
/* Get the dolby surround mode if in 2/0 mode */
|
||||||
|
if(bsi->acmod == 0x2)
|
||||||
|
bsi->dsurmod= bitstream_get(2);
|
||||||
|
|
||||||
|
/* Is the low frequency effects channel on? */
|
||||||
|
bsi->lfeon = bitstream_get(1);
|
||||||
|
|
||||||
|
/* Get the dialogue normalization level */
|
||||||
|
bsi->dialnorm = bitstream_get(5);
|
||||||
|
|
||||||
|
/* Does compression gain exist? */
|
||||||
|
bsi->compre = bitstream_get(1);
|
||||||
|
if (bsi->compre)
|
||||||
|
{
|
||||||
|
/* Get compression gain */
|
||||||
|
bsi->compr = bitstream_get(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does language code exist? */
|
||||||
|
bsi->langcode = bitstream_get(1);
|
||||||
|
if (bsi->langcode)
|
||||||
|
{
|
||||||
|
/* Get langauge code */
|
||||||
|
bsi->langcod = bitstream_get(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does audio production info exist? */
|
||||||
|
bsi->audprodie = bitstream_get(1);
|
||||||
|
if (bsi->audprodie)
|
||||||
|
{
|
||||||
|
/* Get mix level */
|
||||||
|
bsi->mixlevel = bitstream_get(5);
|
||||||
|
|
||||||
|
/* Get room type */
|
||||||
|
bsi->roomtyp = bitstream_get(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're in dual mono mode then get some extra info */
|
||||||
|
if (bsi->acmod ==0)
|
||||||
|
{
|
||||||
|
/* Get the dialogue normalization level two */
|
||||||
|
bsi->dialnorm2 = bitstream_get(5);
|
||||||
|
|
||||||
|
/* Does compression gain two exist? */
|
||||||
|
bsi->compr2e = bitstream_get(1);
|
||||||
|
if (bsi->compr2e)
|
||||||
|
{
|
||||||
|
/* Get compression gain two */
|
||||||
|
bsi->compr2 = bitstream_get(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does language code two exist? */
|
||||||
|
bsi->langcod2e = bitstream_get(1);
|
||||||
|
if (bsi->langcod2e)
|
||||||
|
{
|
||||||
|
/* Get langauge code two */
|
||||||
|
bsi->langcod2 = bitstream_get(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does audio production info two exist? */
|
||||||
|
bsi->audprodi2e = bitstream_get(1);
|
||||||
|
if (bsi->audprodi2e)
|
||||||
|
{
|
||||||
|
/* Get mix level two */
|
||||||
|
bsi->mixlevel2 = bitstream_get(5);
|
||||||
|
|
||||||
|
/* Get room type two */
|
||||||
|
bsi->roomtyp2 = bitstream_get(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the copyright bit */
|
||||||
|
bsi->copyrightb = bitstream_get(1);
|
||||||
|
|
||||||
|
/* Get the original bit */
|
||||||
|
bsi->origbs = bitstream_get(1);
|
||||||
|
|
||||||
|
/* Does timecode one exist? */
|
||||||
|
bsi->timecod1e = bitstream_get(1);
|
||||||
|
|
||||||
|
if(bsi->timecod1e)
|
||||||
|
bsi->timecod1 = bitstream_get(14);
|
||||||
|
|
||||||
|
/* Does timecode two exist? */
|
||||||
|
bsi->timecod2e = bitstream_get(1);
|
||||||
|
|
||||||
|
if(bsi->timecod2e)
|
||||||
|
bsi->timecod2 = bitstream_get(14);
|
||||||
|
|
||||||
|
/* Does addition info exist? */
|
||||||
|
bsi->addbsie = bitstream_get(1);
|
||||||
|
|
||||||
|
if(bsi->addbsie)
|
||||||
|
{
|
||||||
|
/* Get how much info is there */
|
||||||
|
bsi->addbsil = bitstream_get(6);
|
||||||
|
|
||||||
|
/* Get the additional info */
|
||||||
|
for(i=0;i<(bsi->addbsil + 1);i++)
|
||||||
|
bsi->addbsi[i] = bitstream_get(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
stats_print_bsi(bsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* More pain inducing parsing */
|
||||||
|
void
|
||||||
|
parse_audblk(bsi_t *bsi,audblk_t *audblk)
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
|
||||||
|
for (i=0;i < bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
/* Is this channel an interleaved 256 + 256 block ? */
|
||||||
|
audblk->blksw[i] = bitstream_get(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i < bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
/* Should we dither this channel? */
|
||||||
|
audblk->dithflag[i] = bitstream_get(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does dynamic range control exist? */
|
||||||
|
audblk->dynrnge = bitstream_get(1);
|
||||||
|
if (audblk->dynrnge)
|
||||||
|
{
|
||||||
|
/* Get dynamic range info */
|
||||||
|
audblk->dynrng = bitstream_get(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're in dual mono mode then get the second channel DR info */
|
||||||
|
if (bsi->acmod == 0)
|
||||||
|
{
|
||||||
|
/* Does dynamic range control two exist? */
|
||||||
|
audblk->dynrng2e = bitstream_get(1);
|
||||||
|
if (audblk->dynrng2e)
|
||||||
|
{
|
||||||
|
/* Get dynamic range info */
|
||||||
|
audblk->dynrng2 = bitstream_get(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does coupling strategy exist? */
|
||||||
|
audblk->cplstre = bitstream_get(1);
|
||||||
|
if (audblk->cplstre)
|
||||||
|
{
|
||||||
|
/* Is coupling turned on? */
|
||||||
|
audblk->cplinu = bitstream_get(1);
|
||||||
|
if(audblk->cplinu)
|
||||||
|
{
|
||||||
|
for(i=0;i < bsi->nfchans; i++)
|
||||||
|
audblk->chincpl[i] = bitstream_get(1);
|
||||||
|
if(bsi->acmod == 0x2)
|
||||||
|
audblk->phsflginu = bitstream_get(1);
|
||||||
|
audblk->cplbegf = bitstream_get(4);
|
||||||
|
audblk->cplendf = bitstream_get(4);
|
||||||
|
audblk->ncplsubnd = (audblk->cplendf + 2) - audblk->cplbegf + 1;
|
||||||
|
|
||||||
|
/* Calculate the start and end bins of the coupling channel */
|
||||||
|
audblk->cplstrtmant = (audblk->cplbegf * 12) + 37 ;
|
||||||
|
audblk->cplendmant = ((audblk->cplendf + 3) * 12) + 37;
|
||||||
|
|
||||||
|
/* The number of combined subbands is ncplsubnd minus each combined
|
||||||
|
* band */
|
||||||
|
audblk->ncplbnd = audblk->ncplsubnd;
|
||||||
|
|
||||||
|
for(i=1; i< audblk->ncplsubnd; i++)
|
||||||
|
{
|
||||||
|
audblk->cplbndstrc[i] = bitstream_get(1);
|
||||||
|
audblk->ncplbnd -= audblk->cplbndstrc[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audblk->cplinu)
|
||||||
|
{
|
||||||
|
/* Loop through all the channels and get their coupling co-ords */
|
||||||
|
for(i=0;i < bsi->nfchans;i++)
|
||||||
|
{
|
||||||
|
if(!audblk->chincpl[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Is there new coupling co-ordinate info? */
|
||||||
|
audblk->cplcoe[i] = bitstream_get(1);
|
||||||
|
|
||||||
|
if(audblk->cplcoe[i])
|
||||||
|
{
|
||||||
|
audblk->mstrcplco[i] = bitstream_get(2);
|
||||||
|
for(j=0;j < audblk->ncplbnd; j++)
|
||||||
|
{
|
||||||
|
audblk->cplcoexp[i][j] = bitstream_get(4);
|
||||||
|
audblk->cplcomant[i][j] = bitstream_get(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're in dual mono mode, there's going to be some phase info */
|
||||||
|
if( (bsi->acmod == 0x2) && audblk->phsflginu &&
|
||||||
|
(audblk->cplcoe[0] || audblk->cplcoe[1]))
|
||||||
|
{
|
||||||
|
for(j=0;j < audblk->ncplbnd; j++)
|
||||||
|
audblk->phsflg[j] = bitstream_get(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're in dual mono mode, there may be a rematrix strategy */
|
||||||
|
if(bsi->acmod == 0x2)
|
||||||
|
{
|
||||||
|
audblk->rematstr = bitstream_get(1);
|
||||||
|
if(audblk->rematstr)
|
||||||
|
{
|
||||||
|
if (audblk->cplinu == 0)
|
||||||
|
{
|
||||||
|
for(i = 0; i < 4; i++)
|
||||||
|
audblk->rematflg[i] = bitstream_get(1);
|
||||||
|
}
|
||||||
|
if((audblk->cplbegf > 2) && audblk->cplinu)
|
||||||
|
{
|
||||||
|
for(i = 0; i < 4; i++)
|
||||||
|
audblk->rematflg[i] = bitstream_get(1);
|
||||||
|
}
|
||||||
|
if((audblk->cplbegf <= 2) && audblk->cplinu)
|
||||||
|
{
|
||||||
|
for(i = 0; i < 3; i++)
|
||||||
|
audblk->rematflg[i] = bitstream_get(1);
|
||||||
|
}
|
||||||
|
if((audblk->cplbegf == 0) && audblk->cplinu)
|
||||||
|
for(i = 0; i < 2; i++)
|
||||||
|
audblk->rematflg[i] = bitstream_get(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audblk->cplinu)
|
||||||
|
{
|
||||||
|
/* Get the coupling channel exponent strategy */
|
||||||
|
audblk->cplexpstr = bitstream_get(2);
|
||||||
|
audblk->ncplgrps = (audblk->cplendmant - audblk->cplstrtmant) /
|
||||||
|
(3 << (audblk->cplexpstr-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < bsi->nfchans; i++)
|
||||||
|
audblk->chexpstr[i] = bitstream_get(2);
|
||||||
|
|
||||||
|
/* Get the exponent strategy for lfe channel */
|
||||||
|
if(bsi->lfeon)
|
||||||
|
audblk->lfeexpstr = bitstream_get(1);
|
||||||
|
|
||||||
|
/* Determine the bandwidths of all the fbw channels */
|
||||||
|
for(i = 0; i < bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
uint_16 grp_size;
|
||||||
|
|
||||||
|
if(audblk->chexpstr[i] != EXP_REUSE)
|
||||||
|
{
|
||||||
|
if (audblk->cplinu && audblk->chincpl[i])
|
||||||
|
{
|
||||||
|
audblk->endmant[i] = audblk->cplstrtmant;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audblk->chbwcod[i] = bitstream_get(6);
|
||||||
|
audblk->endmant[i] = ((audblk->chbwcod[i] + 12) * 3) + 37;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the number of exponent groups to fetch */
|
||||||
|
grp_size = 3 * (1 << (audblk->chexpstr[i] - 1));
|
||||||
|
audblk->nchgrps[i] = (audblk->endmant[i] - 1 + (grp_size - 3)) / grp_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the coupling exponents if they exist */
|
||||||
|
if(audblk->cplinu && (audblk->cplexpstr != EXP_REUSE))
|
||||||
|
{
|
||||||
|
audblk->cplabsexp = bitstream_get(4);
|
||||||
|
for(i=0;i< audblk->ncplgrps;i++)
|
||||||
|
audblk->cplexps[i] = bitstream_get(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the fwb channel exponents */
|
||||||
|
for(i=0;i < bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
if(audblk->chexpstr[i] != EXP_REUSE)
|
||||||
|
{
|
||||||
|
audblk->exps[i][0] = bitstream_get(4);
|
||||||
|
for(j=1;j<=audblk->nchgrps[i];j++)
|
||||||
|
audblk->exps[i][j] = bitstream_get(7);
|
||||||
|
audblk->gainrng[i] = bitstream_get(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the lfe channel exponents */
|
||||||
|
if(bsi->lfeon && (audblk->lfeexpstr != EXP_REUSE))
|
||||||
|
{
|
||||||
|
audblk->lfeexps[0] = bitstream_get(4);
|
||||||
|
audblk->lfeexps[1] = bitstream_get(7);
|
||||||
|
audblk->lfeexps[2] = bitstream_get(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the parametric bit allocation parameters */
|
||||||
|
audblk->baie = bitstream_get(1);
|
||||||
|
|
||||||
|
if(audblk->baie)
|
||||||
|
{
|
||||||
|
audblk->sdcycod = bitstream_get(2);
|
||||||
|
audblk->fdcycod = bitstream_get(2);
|
||||||
|
audblk->sgaincod = bitstream_get(2);
|
||||||
|
audblk->dbpbcod = bitstream_get(2);
|
||||||
|
audblk->floorcod = bitstream_get(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the SNR off set info if it exists */
|
||||||
|
audblk->snroffste = bitstream_get(1);
|
||||||
|
|
||||||
|
if(audblk->snroffste)
|
||||||
|
{
|
||||||
|
audblk->csnroffst = bitstream_get(6);
|
||||||
|
|
||||||
|
if(audblk->cplinu)
|
||||||
|
{
|
||||||
|
audblk->cplfsnroffst = bitstream_get(4);
|
||||||
|
audblk->cplfgaincod = bitstream_get(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0;i < bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
audblk->fsnroffst[i] = bitstream_get(4);
|
||||||
|
audblk->fgaincod[i] = bitstream_get(3);
|
||||||
|
}
|
||||||
|
if(bsi->lfeon)
|
||||||
|
{
|
||||||
|
|
||||||
|
audblk->lfefsnroffst = bitstream_get(4);
|
||||||
|
audblk->lfefgaincod = bitstream_get(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get coupling leakage info if it exists */
|
||||||
|
if(audblk->cplinu)
|
||||||
|
{
|
||||||
|
audblk->cplleake = bitstream_get(1);
|
||||||
|
|
||||||
|
if(audblk->cplleake)
|
||||||
|
{
|
||||||
|
audblk->cplfleak = bitstream_get(3);
|
||||||
|
audblk->cplsleak = bitstream_get(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the delta bit alloaction info */
|
||||||
|
audblk->deltbaie = bitstream_get(1);
|
||||||
|
|
||||||
|
if(audblk->deltbaie)
|
||||||
|
{
|
||||||
|
if(audblk->cplinu)
|
||||||
|
audblk->cpldeltbae = bitstream_get(2);
|
||||||
|
|
||||||
|
for(i = 0;i < bsi->nfchans; i++)
|
||||||
|
audblk->deltbae[i] = bitstream_get(2);
|
||||||
|
|
||||||
|
if (audblk->cplinu && (audblk->cpldeltbae == DELTA_BIT_NEW))
|
||||||
|
{
|
||||||
|
audblk->cpldeltnseg = bitstream_get(3);
|
||||||
|
for(i = 0;i < audblk->cpldeltnseg + 1; i++)
|
||||||
|
{
|
||||||
|
audblk->cpldeltoffst[i] = bitstream_get(5);
|
||||||
|
audblk->cpldeltlen[i] = bitstream_get(4);
|
||||||
|
audblk->cpldeltba[i] = bitstream_get(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0;i < bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
if (audblk->deltbae[i] == DELTA_BIT_NEW)
|
||||||
|
{
|
||||||
|
audblk->deltnseg[i] = bitstream_get(3);
|
||||||
|
for(j = 0; j < audblk->deltnseg[i] + 1; j++)
|
||||||
|
{
|
||||||
|
audblk->deltoffst[i][j] = bitstream_get(5);
|
||||||
|
audblk->deltlen[i][j] = bitstream_get(4);
|
||||||
|
audblk->deltba[i][j] = bitstream_get(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check to see if there's any dummy info to get */
|
||||||
|
if((audblk->skiple = bitstream_get(1)))
|
||||||
|
{
|
||||||
|
uint_16 skip_data;
|
||||||
|
|
||||||
|
audblk->skipl = bitstream_get(9);
|
||||||
|
//XXX remove
|
||||||
|
//fprintf(stderr,"(parse) skipping %d bytes\n",audblk->skipl);
|
||||||
|
|
||||||
|
for(i = 0; i < audblk->skipl ; i++)
|
||||||
|
{
|
||||||
|
skip_data = bitstream_get(8);
|
||||||
|
//XXX remove
|
||||||
|
//fprintf(stderr,"skipped data %2x\n",skip_data);
|
||||||
|
//if(skip_data != 0)
|
||||||
|
//{
|
||||||
|
//dprintf("(parse) Invalid skipped data %2x\n",skip_data);
|
||||||
|
//exit(1);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stats_print_audblk(bsi,audblk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parse_auxdata(syncinfo_t *syncinfo)
|
||||||
|
{
|
||||||
|
//FIXME keep this now that we don't really need it?
|
||||||
|
#if 0
|
||||||
|
int i;
|
||||||
|
int skip_length;
|
||||||
|
uint_16 crc;
|
||||||
|
uint_16 auxdatae;
|
||||||
|
|
||||||
|
skip_length = (syncinfo->frame_size * 16) - bitstream_get_total_bits() - 17 - 1;
|
||||||
|
|
||||||
|
//XXX remove
|
||||||
|
//dprintf("(auxdata) skipping %d auxbits\n",skip_length);
|
||||||
|
|
||||||
|
for(i=0; i < skip_length; i++)
|
||||||
|
//printf("Skipped bit %i\n",(uint_16)bitstream_get(1));
|
||||||
|
bitstream_get(1);
|
||||||
|
|
||||||
|
//get the auxdata exists bit
|
||||||
|
auxdatae = bitstream_get(1);
|
||||||
|
|
||||||
|
//XXX remove
|
||||||
|
//dprintf("auxdatae = %i\n",auxdatae);
|
||||||
|
|
||||||
|
//Skip the CRC reserved bit
|
||||||
|
bitstream_get(1);
|
||||||
|
|
||||||
|
//Get the crc
|
||||||
|
crc = bitstream_get(16);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
28
ac3dec/parse.h
Normal file
28
ac3dec/parse.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* parse.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void parse_syncinfo(syncinfo_t *syncinfo,uint_8 *data);
|
||||||
|
void parse_audblk(bsi_t *bsi,audblk_t *audblk);
|
||||||
|
void parse_bsi(bsi_t *bsi);
|
||||||
|
void parse_auxdata(syncinfo_t *syncinfo);
|
||||||
|
|
83
ac3dec/rematrix.c
Normal file
83
ac3dec/rematrix.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* rematrix.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - July 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "decode.h"
|
||||||
|
#include "rematrix.h"
|
||||||
|
|
||||||
|
struct rematrix_band_s
|
||||||
|
{
|
||||||
|
uint_32 start;
|
||||||
|
uint_32 end;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rematrix_band_s rematrix_band[] = { {13,24}, {25,36}, {37 ,60}, {61,252}};
|
||||||
|
|
||||||
|
static inline uint_32 min(uint_32 a,uint_32 b);
|
||||||
|
|
||||||
|
static inline uint_32
|
||||||
|
min(uint_32 a,uint_32 b)
|
||||||
|
{
|
||||||
|
return (a < b ? a : b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine simply does stereo rematixing for the 2 channel
|
||||||
|
* stereo mode */
|
||||||
|
void rematrix(audblk_t *audblk, stream_samples_t samples)
|
||||||
|
{
|
||||||
|
uint_32 num_bands;
|
||||||
|
uint_32 start;
|
||||||
|
uint_32 end;
|
||||||
|
uint_32 i,j;
|
||||||
|
float left,right;
|
||||||
|
|
||||||
|
if(!audblk->cplinu || audblk->cplbegf > 2)
|
||||||
|
num_bands = 4;
|
||||||
|
else if (audblk->cplbegf > 0)
|
||||||
|
num_bands = 3;
|
||||||
|
else
|
||||||
|
num_bands = 2;
|
||||||
|
|
||||||
|
for(i=0;i < num_bands; i++)
|
||||||
|
{
|
||||||
|
if(!audblk->rematflg[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
start = rematrix_band[i].start;
|
||||||
|
end = min(rematrix_band[i].end ,12 * audblk->cplbegf + 36);
|
||||||
|
|
||||||
|
for(j=start;j < end; j++)
|
||||||
|
{
|
||||||
|
left = samples[0][j] + samples[1][j];
|
||||||
|
right = samples[0][j] - samples[1][j];
|
||||||
|
samples[0][j] = left;
|
||||||
|
samples[1][j] = right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
ac3dec/rematrix.h
Normal file
25
ac3dec/rematrix.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* rematrix.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - July 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void rematrix(audblk_t *audblk, stream_samples_t samples);
|
131
ac3dec/sanity_check.c
Normal file
131
ac3dec/sanity_check.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* sanity_check.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
#include "sanity_check.h"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
sanity_check_init(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk)
|
||||||
|
{
|
||||||
|
syncinfo->magic = AC3_MAGIC_NUMBER;
|
||||||
|
bsi->magic = AC3_MAGIC_NUMBER;
|
||||||
|
audblk->magic1 = AC3_MAGIC_NUMBER;
|
||||||
|
audblk->magic2 = AC3_MAGIC_NUMBER;
|
||||||
|
audblk->magic3 = AC3_MAGIC_NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sanity_check(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(syncinfo->magic != AC3_MAGIC_NUMBER)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- syncinfo magic number **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bsi->magic != AC3_MAGIC_NUMBER)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- bsi magic number **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audblk->magic1 != AC3_MAGIC_NUMBER)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- audblk magic number 1 **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audblk->magic2 != AC3_MAGIC_NUMBER)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- audblk magic number 2 **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audblk->magic3 != AC3_MAGIC_NUMBER)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- audblk magic number 3 **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0;i < 5 ; i++)
|
||||||
|
{
|
||||||
|
if (audblk->fbw_exp[i][255] !=0 || audblk->fbw_exp[i][254] !=0 ||
|
||||||
|
audblk->fbw_exp[i][253] !=0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- fbw_exp out of bounds **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audblk->fbw_bap[i][255] !=0 || audblk->fbw_bap[i][254] !=0 ||
|
||||||
|
audblk->fbw_bap[i][253] !=0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- fbw_bap out of bounds **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audblk->cpl_exp[255] !=0 || audblk->cpl_exp[254] !=0 ||
|
||||||
|
audblk->cpl_exp[253] !=0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- cpl_exp out of bounds **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audblk->cpl_bap[255] !=0 || audblk->cpl_bap[254] !=0 ||
|
||||||
|
audblk->cpl_bap[253] !=0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- cpl_bap out of bounds **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audblk->cplmant[255] !=0 || audblk->cplmant[254] !=0 ||
|
||||||
|
audblk->cplmant[253] !=0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- cpl_mant out of bounds **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((audblk->cplinu == 1) && (audblk->cplbegf > (audblk->cplendf+2)))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- cpl params inconsistent **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i < bsi->nfchans; i++)
|
||||||
|
{
|
||||||
|
if((audblk->chincpl[i] == 0) && (audblk->chbwcod[i] > 60))
|
||||||
|
{
|
||||||
|
fprintf(stderr,"\n** Sanity check failed -- chbwcod too big **");
|
||||||
|
error_flag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
27
ac3dec/sanity_check.h
Normal file
27
ac3dec/sanity_check.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* sanity_check.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AC3_MAGIC_NUMBER 0xdeadbeef
|
||||||
|
|
||||||
|
void sanity_check_init(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk);
|
||||||
|
void sanity_check(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk);
|
178
ac3dec/stats.c
Normal file
178
ac3dec/stats.c
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* stats.c
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
//#include "config.h"
|
||||||
|
#include "ac3.h"
|
||||||
|
#include "ac3_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "decode.h"
|
||||||
|
#include "stats.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char *service_ids[8] =
|
||||||
|
{
|
||||||
|
"CM","ME","VI","HI",
|
||||||
|
"D", "C","E", "VO"
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mixlev_s
|
||||||
|
{
|
||||||
|
float clev;
|
||||||
|
char *desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mixlev_s cmixlev_tbl[4] =
|
||||||
|
{
|
||||||
|
{0.707, "(-3.0 dB)"}, {0.595, "(-4.5 dB)"},
|
||||||
|
{0.500, "(-6.0 dB)"}, {1.0, "Invalid"}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mixlev_s smixlev_tbl[4] =
|
||||||
|
{
|
||||||
|
{0.707, "(-3.0 dB)"}, {0.500, "(-6.0 dB)"},
|
||||||
|
{ 0.0, "off "}, { 1.0, "Invalid"}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *language[128] =
|
||||||
|
{
|
||||||
|
"unknown", "Albanian", "Breton", "Catalan", "Croatian", "Welsh", "Czech", "Danish",
|
||||||
|
"German", "English", "Spanish", "Esperanto", "Estonian", "Basque", "Faroese", "French",
|
||||||
|
"Frisian", "Irish", "Gaelic", "Galician", "Icelandic", "Italian", "Lappish", "Latin",
|
||||||
|
"Latvian", "Luxembourgian", "Lithuanian", "Hungarian", "Maltese", "Dutch", "Norwegian", "Occitan",
|
||||||
|
"Polish", "Portugese", "Romanian", "Romansh", "Serbian", "Slovak", "Slovene", "Finnish",
|
||||||
|
"Swedish", "Turkish", "Flemish", "Walloon", "0x2c", "0x2d", "0x2e", "0x2f",
|
||||||
|
"0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37",
|
||||||
|
"0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f",
|
||||||
|
"background", "0x41", "0x42", "0x43", "0x44", "Zulu", "Vietnamese", "Uzbek",
|
||||||
|
"Urdu", "Ukrainian", "Thai", "Telugu", "Tatar", "Tamil", "Tadzhik", "Swahili",
|
||||||
|
"Sranan Tongo", "Somali", "Sinhalese", "Shona", "Serbo-Croat", "Ruthenian", "Russian", "Quechua",
|
||||||
|
"Pustu", "Punjabi", "Persian", "Papamiento", "Oriya", "Nepali", "Ndebele", "Marathi",
|
||||||
|
"Moldavian", "Malaysian", "Malagasay", "Macedonian", "Laotian", "Korean", "Khmer", "Kazakh",
|
||||||
|
"Kannada", "Japanese", "Indonesian", "Hindi", "Hebrew", "Hausa", "Gurani", "Gujurati",
|
||||||
|
"Greek", "Georgian", "Fulani", "Dari", "Churash", "Chinese", "Burmese", "Bulgarian",
|
||||||
|
"Bengali", "Belorussian", "Bambora", "Azerbijani", "Assamese", "Armenian", "Arabic", "Amharic"
|
||||||
|
};
|
||||||
|
|
||||||
|
void stats_print_banner(syncinfo_t *syncinfo,bsi_t *bsi)
|
||||||
|
{
|
||||||
|
fprintf(stdout,"ac3dec-0.6.2-cvs (C) 2000 Aaron Holtzman (aholtzma@ess.engr.uvic.ca)\n");
|
||||||
|
|
||||||
|
fprintf(stdout,"%d.%d Mode ",bsi->nfchans,bsi->lfeon);
|
||||||
|
fprintf(stdout,"%2.1f KHz",syncinfo->sampling_rate * 1e-3);
|
||||||
|
fprintf(stdout,"%4d kbps ",syncinfo->bit_rate);
|
||||||
|
if (bsi->langcode && (bsi->langcod < 128))
|
||||||
|
fprintf(stdout,"%s ", language[bsi->langcod]);
|
||||||
|
|
||||||
|
switch(bsi->bsmod)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
fprintf(stdout,"Complete Main Audio Service");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
fprintf(stdout,"Music and Effects Audio Service");
|
||||||
|
case 2:
|
||||||
|
fprintf(stdout,"Visually Impaired Audio Service");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
fprintf(stdout,"Hearing Impaired Audio Service");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fprintf(stdout,"Dialogue Audio Service");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
fprintf(stdout,"Commentary Audio Service");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
fprintf(stdout,"Emergency Audio Service");
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
fprintf(stdout,"Voice Over Audio Service");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stdout,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void stats_print_syncinfo(syncinfo_t *syncinfo)
|
||||||
|
{
|
||||||
|
dprintf("(syncinfo) ");
|
||||||
|
|
||||||
|
switch (syncinfo->fscod)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
dprintf("32 KHz ");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
dprintf("44.1 KHz ");
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
dprintf("48 KHz ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintf("Invalid sampling rate ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("%4d kbps %4d words per frame\n",syncinfo->bit_rate,
|
||||||
|
syncinfo->frame_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void stats_print_bsi(bsi_t *bsi)
|
||||||
|
{
|
||||||
|
dprintf("(bsi) ");
|
||||||
|
dprintf("%s",service_ids[bsi->bsmod]);
|
||||||
|
dprintf(" %d.%d Mode ",bsi->nfchans,bsi->lfeon);
|
||||||
|
if ((bsi->acmod & 0x1) && (bsi->acmod != 0x1))
|
||||||
|
dprintf(" Centre Mix Level %s ",cmixlev_tbl[bsi->cmixlev].desc);
|
||||||
|
if (bsi->acmod & 0x4)
|
||||||
|
dprintf(" Sur Mix Level %s ",smixlev_tbl[bsi->cmixlev].desc);
|
||||||
|
dprintf("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char *exp_strat_tbl[4] = {"R ","D15 ","D25 ","D45 "};
|
||||||
|
|
||||||
|
void stats_print_audblk(bsi_t *bsi,audblk_t *audblk)
|
||||||
|
{
|
||||||
|
uint_32 i;
|
||||||
|
|
||||||
|
dprintf("(audblk) ");
|
||||||
|
dprintf("%s ",audblk->cplinu ? "cpl on " : "cpl off");
|
||||||
|
dprintf("%s ",audblk->baie? "bai " : " ");
|
||||||
|
dprintf("%s ",audblk->snroffste? "snroffst " : " ");
|
||||||
|
dprintf("%s ",audblk->deltbaie? "deltba " : " ");
|
||||||
|
dprintf("%s ",audblk->phsflginu? "phsflg " : " ");
|
||||||
|
dprintf("(%s %s %s %s %s) ",exp_strat_tbl[audblk->chexpstr[0]],
|
||||||
|
exp_strat_tbl[audblk->chexpstr[1]],exp_strat_tbl[audblk->chexpstr[2]],
|
||||||
|
exp_strat_tbl[audblk->chexpstr[3]],exp_strat_tbl[audblk->chexpstr[4]]);
|
||||||
|
dprintf("[");
|
||||||
|
for(i=0;i<bsi->nfchans;i++)
|
||||||
|
dprintf("%1d",audblk->blksw[i]);
|
||||||
|
dprintf("]");
|
||||||
|
|
||||||
|
dprintf("\n");
|
||||||
|
}
|
27
ac3dec/stats.h
Normal file
27
ac3dec/stats.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* stats.h
|
||||||
|
*
|
||||||
|
* Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
*
|
||||||
|
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
|
||||||
|
*
|
||||||
|
* ac3dec 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.
|
||||||
|
*
|
||||||
|
* ac3dec 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 GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void stats_print_syncinfo(syncinfo_t *syncinfo);
|
||||||
|
void stats_print_bsi(bsi_t *bsi);
|
||||||
|
void stats_print_audblk(bsi_t *bsi,audblk_t *audblk);
|
||||||
|
void stats_print_banner(syncinfo_t *syncinfo,bsi_t *bsi);
|
4
config.h
4
config.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: config.h 1.55 2001/07/27 13:32:53 kls Exp $
|
* $Id: config.h 1.56 2001/08/02 15:11:10 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CONFIG_H
|
#ifndef __CONFIG_H
|
||||||
@ -19,7 +19,7 @@
|
|||||||
#include "eit.h"
|
#include "eit.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
#define VDRVERSION "0.85"
|
#define VDRVERSION "0.86"
|
||||||
|
|
||||||
#define MaxBuffer 10000
|
#define MaxBuffer 10000
|
||||||
|
|
||||||
|
11
dvbapi.h
11
dvbapi.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbapi.h 1.42 2001/07/27 11:40:38 kls Exp $
|
* $Id: dvbapi.h 1.43 2001/08/02 14:50:48 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DVBAPI_H
|
#ifndef __DVBAPI_H
|
||||||
@ -26,7 +26,9 @@
|
|||||||
#include <ost/audio.h>
|
#include <ost/audio.h>
|
||||||
#include <ost/osd.h>
|
#include <ost/osd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "dvbosd.h"
|
#include "dvbosd.h"
|
||||||
|
#include "dvd.h"
|
||||||
#include "eit.h"
|
#include "eit.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
||||||
@ -44,7 +46,9 @@ int HMSFToIndex(const char *HMSF);
|
|||||||
class cChannel;
|
class cChannel;
|
||||||
|
|
||||||
class cRecordBuffer;
|
class cRecordBuffer;
|
||||||
|
class cPlayBuffer;
|
||||||
class cReplayBuffer;
|
class cReplayBuffer;
|
||||||
|
class cDVDplayBuffer;
|
||||||
class cTransferBuffer;
|
class cTransferBuffer;
|
||||||
class cCuttingBuffer;
|
class cCuttingBuffer;
|
||||||
|
|
||||||
@ -60,6 +64,7 @@ public:
|
|||||||
class cDvbApi {
|
class cDvbApi {
|
||||||
friend class cRecordBuffer;
|
friend class cRecordBuffer;
|
||||||
friend class cReplayBuffer;
|
friend class cReplayBuffer;
|
||||||
|
friend class cDVDplayBuffer;
|
||||||
friend class cTransferBuffer;
|
friend class cTransferBuffer;
|
||||||
private:
|
private:
|
||||||
int videoDev;
|
int videoDev;
|
||||||
@ -202,7 +207,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
cRecordBuffer *recordBuffer;
|
cRecordBuffer *recordBuffer;
|
||||||
cReplayBuffer *replayBuffer;
|
cPlayBuffer *replayBuffer;
|
||||||
int ca;
|
int ca;
|
||||||
int priority;
|
int priority;
|
||||||
int Ca(void) { return ca; }
|
int Ca(void) { return ca; }
|
||||||
@ -238,6 +243,8 @@ public:
|
|||||||
// Starts replaying the given file.
|
// Starts replaying the given file.
|
||||||
// If there is already a replay session active, it will be stopped
|
// If there is already a replay session active, it will be stopped
|
||||||
// and the new file will be played back.
|
// and the new file will be played back.
|
||||||
|
bool StartDVDplay(cDVD *dvd, int TitleID);//XXX dvd parameter necessary???
|
||||||
|
// Starts replaying the given TitleID on the DVD.
|
||||||
void StopReplay(void);
|
void StopReplay(void);
|
||||||
// Stops the current replay session (if any).
|
// Stops the current replay session (if any).
|
||||||
void Pause(void);
|
void Pause(void);
|
||||||
|
128
dvd.c
Normal file
128
dvd.c
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* dvd.c: Functions for handling DVDs
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* Initially written by Andreas Schultz <aschultz@warp10.net>
|
||||||
|
*
|
||||||
|
* $Id: dvd.c 1.1 2001/08/03 12:35:38 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
//XXX //#define DVDDEBUG 1
|
||||||
|
//XXX //#define DEBUG_BUFFER 1
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/cdrom.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "dvd.h"
|
||||||
|
|
||||||
|
// --- cDVD ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const char *cDVD::deviceName = "/dev/dvd";
|
||||||
|
cDVD *cDVD::dvdInstance = NULL;
|
||||||
|
|
||||||
|
cDVD *cDVD::getDVD(void)
|
||||||
|
{
|
||||||
|
if (!dvdInstance)
|
||||||
|
new cDVD;
|
||||||
|
return dvdInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
cDVD::cDVD(void)
|
||||||
|
{
|
||||||
|
dvd = NULL;
|
||||||
|
title = NULL;
|
||||||
|
vmg_file = NULL;
|
||||||
|
vts_file = NULL;
|
||||||
|
dvdInstance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cDVD::~cDVD()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDVD::SetDeviceName(const char *DeviceName)
|
||||||
|
{
|
||||||
|
deviceName = strdup(DeviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cDVD::DeviceName(void)
|
||||||
|
{
|
||||||
|
return deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDVD::Open(void)
|
||||||
|
{
|
||||||
|
if (!dvd)
|
||||||
|
dvd = DVDOpen(deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDVD::Close(void)
|
||||||
|
{
|
||||||
|
#ifdef DVDDEBUG
|
||||||
|
dsyslog(LOG_INFO, "DVD: cDVD::Close(%p): vts: %p, vmg: %p, title: %p, dvd: %p", this, vts_file, vmg_file, title, dvd);
|
||||||
|
#endif
|
||||||
|
if (vts_file)
|
||||||
|
ifoClose(vts_file);
|
||||||
|
if (vmg_file)
|
||||||
|
ifoClose(vmg_file);
|
||||||
|
if (title)
|
||||||
|
DVDCloseFile(title);
|
||||||
|
if (dvd)
|
||||||
|
DVDClose(dvd);
|
||||||
|
vts_file = NULL;
|
||||||
|
vmg_file = NULL;
|
||||||
|
title = NULL;
|
||||||
|
dvd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDVD::Eject(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
Close();
|
||||||
|
// ignore all errors try our best :-)
|
||||||
|
if ((fd = open(deviceName, O_RDONLY)) > 0) {
|
||||||
|
ioctl(fd, CDROMEJECT, 0);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ifo_handle_t *cDVD::openVMG(void)
|
||||||
|
{
|
||||||
|
if (!isValid())
|
||||||
|
return NULL;
|
||||||
|
if (!vmg_file)
|
||||||
|
vmg_file = ifoOpen(dvd, 0);
|
||||||
|
return vmg_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifo_handle_t *cDVD::openVTS(int TitleSet)
|
||||||
|
{
|
||||||
|
if (!isValid())
|
||||||
|
return NULL;
|
||||||
|
if (vts_file && (titleset != TitleSet)) {
|
||||||
|
ifoClose(vts_file);
|
||||||
|
vts_file = NULL;
|
||||||
|
}
|
||||||
|
if (!vts_file) {
|
||||||
|
titleset = TitleSet;
|
||||||
|
vts_file = ifoOpen(dvd, TitleSet);
|
||||||
|
}
|
||||||
|
return vts_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
dvd_file_t *cDVD::openTitle(int Title, dvd_read_domain_t domain)
|
||||||
|
{
|
||||||
|
if (!isValid())
|
||||||
|
return NULL;
|
||||||
|
if (title)
|
||||||
|
DVDCloseFile(title);
|
||||||
|
title = DVDOpenFile(dvd, Title, domain);
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
46
dvd.h
Normal file
46
dvd.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* dvd.h: Functions for handling DVDs
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* Initially written by Andreas Schultz <aschultz@warp10.net>
|
||||||
|
*
|
||||||
|
* $Id: dvd.h 1.1 2001/08/03 12:35:42 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DVD_H
|
||||||
|
#define __DVD_H
|
||||||
|
|
||||||
|
#include <dvdread/dvd_reader.h>
|
||||||
|
#include <dvdread/ifo_types.h>
|
||||||
|
#include <dvdread/ifo_read.h>
|
||||||
|
#include <dvdread/dvd_udf.h>
|
||||||
|
#include <dvdread/nav_read.h>
|
||||||
|
#include <dvdread/nav_print.h>
|
||||||
|
|
||||||
|
class cDVD {
|
||||||
|
private:
|
||||||
|
static cDVD *dvdInstance;
|
||||||
|
static const char *deviceName;
|
||||||
|
dvd_reader_t *dvd;
|
||||||
|
dvd_file_t *title;
|
||||||
|
ifo_handle_t *vmg_file;
|
||||||
|
ifo_handle_t *vts_file;
|
||||||
|
int titleset;
|
||||||
|
public:
|
||||||
|
cDVD(void);
|
||||||
|
~cDVD();
|
||||||
|
void Open(void);
|
||||||
|
void Close(void);
|
||||||
|
void Eject(void);
|
||||||
|
bool isValid(void) { return (dvd != NULL); }
|
||||||
|
ifo_handle_t *openVMG(void);
|
||||||
|
ifo_handle_t *openVTS(int TitleSet);
|
||||||
|
dvd_file_t *openTitle(int Title, dvd_read_domain_t domain);
|
||||||
|
static cDVD *getDVD(void);
|
||||||
|
static void SetDeviceName(const char *DeviceName);
|
||||||
|
static const char *DeviceName(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__DVD_H
|
22
i18n.c
22
i18n.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: i18n.c 1.26 2001/07/27 13:32:43 kls Exp $
|
* $Id: i18n.c 1.27 2001/08/02 14:40:16 kls Exp $
|
||||||
*
|
*
|
||||||
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
|
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
|
||||||
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
|
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
|
||||||
@ -113,6 +113,15 @@ const tPhrase Phrases[] = {
|
|||||||
"Enregistrements",
|
"Enregistrements",
|
||||||
"Opptak",
|
"Opptak",
|
||||||
},
|
},
|
||||||
|
{ "DVD",
|
||||||
|
"DVD",
|
||||||
|
"DVD",
|
||||||
|
"DVD",
|
||||||
|
"DVD",
|
||||||
|
"DVD",
|
||||||
|
"DVD",
|
||||||
|
"DVD",
|
||||||
|
},
|
||||||
{ "Setup",
|
{ "Setup",
|
||||||
"Einstellungen",
|
"Einstellungen",
|
||||||
"Nastavitve",
|
"Nastavitve",
|
||||||
@ -194,7 +203,7 @@ const tPhrase Phrases[] = {
|
|||||||
"Prochains programmes",
|
"Prochains programmes",
|
||||||
"Hvilket program er neste?",
|
"Hvilket program er neste?",
|
||||||
},
|
},
|
||||||
// Button texts (must not be more than 10 characters!):
|
// Button texts (should not be more than 10 characters!):
|
||||||
{ "Edit",
|
{ "Edit",
|
||||||
"Editieren",
|
"Editieren",
|
||||||
"Uredi",
|
"Uredi",
|
||||||
@ -321,6 +330,15 @@ const tPhrase Phrases[] = {
|
|||||||
"Langue",
|
"Langue",
|
||||||
"Språk",
|
"Språk",
|
||||||
},
|
},
|
||||||
|
{ "Eject DVD",
|
||||||
|
"DVD auswerfen",
|
||||||
|
"", // TODO
|
||||||
|
"", // TODO
|
||||||
|
"", // TODO
|
||||||
|
"", // TODO
|
||||||
|
"", // TODO
|
||||||
|
"", // TODO
|
||||||
|
},
|
||||||
// Confirmations:
|
// Confirmations:
|
||||||
{ "Delete channel?",
|
{ "Delete channel?",
|
||||||
"Kanal löschen?",
|
"Kanal löschen?",
|
||||||
|
166
menu.c
166
menu.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menu.c 1.89 2001/07/31 15:28:10 kls Exp $
|
* $Id: menu.c 1.90 2001/08/03 14:18:08 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@ -1590,6 +1590,78 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cMenuDVDItem ----------------------------------------------------------
|
||||||
|
|
||||||
|
class cMenuDVDItem : public cOsdItem {
|
||||||
|
private:
|
||||||
|
int title;
|
||||||
|
int chapters;
|
||||||
|
virtual void Set(void);
|
||||||
|
public:
|
||||||
|
cMenuDVDItem(int Title, int Chapters);
|
||||||
|
int Title(void) { return title; }
|
||||||
|
};
|
||||||
|
|
||||||
|
cMenuDVDItem::cMenuDVDItem(int Title, int Chapters)
|
||||||
|
{
|
||||||
|
title = Title;
|
||||||
|
chapters = Chapters;
|
||||||
|
Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuDVDItem::Set(void)
|
||||||
|
{
|
||||||
|
char *buffer = NULL;
|
||||||
|
asprintf(&buffer, " %2d.\tTitle - \t%2d\tChapters", title + 1, chapters);
|
||||||
|
SetText(buffer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cMenuDVD --------------------------------------------------------------
|
||||||
|
|
||||||
|
cMenuDVD::cMenuDVD(void)
|
||||||
|
:cOsdMenu(tr("DVD"), 5, 8, 3)
|
||||||
|
{
|
||||||
|
if ((dvd = cDVD::getDVD())) {
|
||||||
|
dvd->Open();
|
||||||
|
ifo_handle_t *vmg = dvd->openVMG();
|
||||||
|
if (vmg) {
|
||||||
|
dsyslog(LOG_INFO, "DVD: vmg: %p", vmg);//XXX
|
||||||
|
tt_srpt_t *tt_srpt = vmg->tt_srpt;
|
||||||
|
dsyslog(LOG_INFO, "DVD: tt_srpt: %p", tt_srpt);//XXX
|
||||||
|
for (int i = 0; i < tt_srpt->nr_of_srpts; i++)
|
||||||
|
Add(new cMenuDVDItem(i, tt_srpt->title[i].nr_of_ptts));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetHelp(tr("Play"), NULL, NULL, NULL);
|
||||||
|
Display();
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuDVD::Play(void)
|
||||||
|
{
|
||||||
|
cMenuDVDItem *ri = (cMenuDVDItem *)Get(Current());
|
||||||
|
if (ri) {
|
||||||
|
cReplayControl::SetDVD(dvd, ri->Title());
|
||||||
|
isyslog(LOG_INFO, "DVD: playing title %d", ri->Title());
|
||||||
|
return osReplay;
|
||||||
|
}
|
||||||
|
return osContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuDVD::ProcessKey(eKeys Key)
|
||||||
|
{
|
||||||
|
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||||
|
|
||||||
|
if (state == osUnknown) {
|
||||||
|
switch (Key) {
|
||||||
|
case kOk:
|
||||||
|
case kRed: return Play();
|
||||||
|
case kMenu: return osEnd;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cMenuSetup ------------------------------------------------------------
|
// --- cMenuSetup ------------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetup : public cOsdMenu {
|
class cMenuSetup : public cOsdMenu {
|
||||||
@ -1714,40 +1786,46 @@ eOSState cMenuCommands::ProcessKey(eKeys Key)
|
|||||||
|
|
||||||
#define STOP_RECORDING tr(" Stop recording ")
|
#define STOP_RECORDING tr(" Stop recording ")
|
||||||
|
|
||||||
static const char *hk(int n, const char *s)
|
|
||||||
{
|
|
||||||
static char buffer[32];
|
|
||||||
snprintf(buffer, sizeof(buffer), " %d %s", n, s);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
cMenuMain::cMenuMain(bool Replaying)
|
cMenuMain::cMenuMain(bool Replaying)
|
||||||
:cOsdMenu(tr("Main"))
|
:cOsdMenu(tr("Main"))
|
||||||
{
|
{
|
||||||
Add(new cOsdItem(hk(1, tr("Schedule")), osSchedule));
|
digit = 0;
|
||||||
Add(new cOsdItem(hk(2, tr("Channels")), osChannels));
|
Add(new cOsdItem(hk(tr("Schedule")), osSchedule));
|
||||||
Add(new cOsdItem(hk(3, tr("Timers")), osTimers));
|
Add(new cOsdItem(hk(tr("Channels")), osChannels));
|
||||||
Add(new cOsdItem(hk(4, tr("Recordings")), osRecordings));
|
Add(new cOsdItem(hk(tr("Timers")), osTimers));
|
||||||
Add(new cOsdItem(hk(5, tr("Setup")), osSetup));
|
Add(new cOsdItem(hk(tr("Recordings")), osRecordings));
|
||||||
|
Add(new cOsdItem(hk(tr("DVD")), osDVD));
|
||||||
|
Add(new cOsdItem(hk(tr("Setup")), osSetup));
|
||||||
if (Commands.Count())
|
if (Commands.Count())
|
||||||
Add(new cOsdItem(hk(6, tr("Commands")), osCommands));
|
Add(new cOsdItem(hk(tr("Commands")), osCommands));
|
||||||
if (Replaying)
|
if (Replaying)
|
||||||
Add(new cOsdItem(tr(" Stop replaying"), osStopReplay));
|
Add(new cOsdItem(hk(tr(" Stop replaying")), osStopReplay));
|
||||||
const char *s = NULL;
|
const char *s = NULL;
|
||||||
while ((s = cRecordControls::GetInstantId(s)) != NULL) {
|
while ((s = cRecordControls::GetInstantId(s)) != NULL) {
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
asprintf(&buffer, "%s%s", STOP_RECORDING, s);
|
asprintf(&buffer, "%s%s", STOP_RECORDING, s);
|
||||||
Add(new cOsdItem(buffer, osStopRecord));
|
Add(new cOsdItem(hk(buffer), osStopRecord));
|
||||||
delete buffer;
|
delete buffer;
|
||||||
}
|
}
|
||||||
if (cVideoCutter::Active())
|
if (cVideoCutter::Active())
|
||||||
Add(new cOsdItem(tr(" Cancel editing"), osCancelEdit));
|
Add(new cOsdItem(hk(tr(" Cancel editing")), osCancelEdit));
|
||||||
SetHelp(tr("Record"), cDvbApi::PrimaryDvbApi->CanToggleAudioTrack() ? tr("Language") : NULL, NULL, cReplayControl::LastReplayed() ? tr("Resume") : NULL);
|
SetHelp(tr("Record"), cDvbApi::PrimaryDvbApi->CanToggleAudioTrack() ? tr("Language") : NULL, /*XXX only if DVD loaded?*/tr("Eject DVD"), cReplayControl::LastReplayed() ? tr("Resume") : NULL);
|
||||||
Display();
|
Display();
|
||||||
lastActivity = time(NULL);
|
lastActivity = time(NULL);
|
||||||
SetHasHotkeys();
|
SetHasHotkeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *cMenuMain::hk(const char *s)
|
||||||
|
{
|
||||||
|
static char buffer[32];
|
||||||
|
if (digit < 9) {
|
||||||
|
snprintf(buffer, sizeof(buffer), " %d %s", ++digit, s);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
eOSState cMenuMain::ProcessKey(eKeys Key)
|
eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||||
@ -1757,6 +1835,7 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
|||||||
case osChannels: return AddSubMenu(new cMenuChannels);
|
case osChannels: return AddSubMenu(new cMenuChannels);
|
||||||
case osTimers: return AddSubMenu(new cMenuTimers);
|
case osTimers: return AddSubMenu(new cMenuTimers);
|
||||||
case osRecordings: return AddSubMenu(new cMenuRecordings);
|
case osRecordings: return AddSubMenu(new cMenuRecordings);
|
||||||
|
case osDVD: return AddSubMenu(new cMenuDVD);
|
||||||
case osSetup: return AddSubMenu(new cMenuSetup);
|
case osSetup: return AddSubMenu(new cMenuSetup);
|
||||||
case osCommands: return AddSubMenu(new cMenuCommands);
|
case osCommands: return AddSubMenu(new cMenuCommands);
|
||||||
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
|
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
|
||||||
@ -1773,22 +1852,30 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: switch (Key) {
|
default: switch (Key) {
|
||||||
case kMenu: state = osEnd; break;
|
case kMenu: state = osEnd; break;
|
||||||
case kRed: if (!HasSubMenu())
|
case kRed: if (!HasSubMenu())
|
||||||
state = osRecord;
|
state = osRecord;
|
||||||
break;
|
break;
|
||||||
case kGreen: if (!HasSubMenu()) {
|
case kGreen: if (!HasSubMenu()) {
|
||||||
if (cDvbApi::PrimaryDvbApi->CanToggleAudioTrack()) {
|
if (cDvbApi::PrimaryDvbApi->CanToggleAudioTrack()) {
|
||||||
Interface->Clear();
|
Interface->Clear();
|
||||||
cDvbApi::PrimaryDvbApi->ToggleAudioTrack();
|
cDvbApi::PrimaryDvbApi->ToggleAudioTrack();
|
||||||
state = osEnd;
|
state = osEnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kBlue: if (!HasSubMenu())
|
case kYellow: if (!HasSubMenu()) {
|
||||||
state = osReplay;
|
cDVD *dvd;
|
||||||
break;
|
if ((dvd = cDVD::getDVD())) {
|
||||||
default: break;
|
dvd->Eject();
|
||||||
|
state = osEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kBlue: if (!HasSubMenu())
|
||||||
|
state = osReplay;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Key != kNone)
|
if (Key != kNone)
|
||||||
@ -2144,6 +2231,8 @@ void cProgressBar::Mark(int x, bool Start, bool Current)
|
|||||||
|
|
||||||
char *cReplayControl::fileName = NULL;
|
char *cReplayControl::fileName = NULL;
|
||||||
char *cReplayControl::title = NULL;
|
char *cReplayControl::title = NULL;
|
||||||
|
cDVD *cReplayControl::dvd = NULL;//XXX
|
||||||
|
int cReplayControl::titleid = 0;//XXX
|
||||||
|
|
||||||
cReplayControl::cReplayControl(void)
|
cReplayControl::cReplayControl(void)
|
||||||
{
|
{
|
||||||
@ -2155,6 +2244,8 @@ cReplayControl::cReplayControl(void)
|
|||||||
marks.Load(fileName);
|
marks.Load(fileName);
|
||||||
dvbApi->StartReplay(fileName);
|
dvbApi->StartReplay(fileName);
|
||||||
}
|
}
|
||||||
|
else if (dvd)
|
||||||
|
dvbApi->StartDVDplay(dvd, titleid);//XXX
|
||||||
}
|
}
|
||||||
|
|
||||||
cReplayControl::~cReplayControl()
|
cReplayControl::~cReplayControl()
|
||||||
@ -2171,6 +2262,13 @@ void cReplayControl::SetRecording(const char *FileName, const char *Title)
|
|||||||
title = Title ? strdup(Title) : NULL;
|
title = Title ? strdup(Title) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cReplayControl::SetDVD(cDVD *DVD, int Title)//XXX
|
||||||
|
{
|
||||||
|
SetRecording(NULL, NULL);
|
||||||
|
dvd = DVD;
|
||||||
|
titleid = Title;
|
||||||
|
}
|
||||||
|
|
||||||
const char *cReplayControl::LastReplayed(void)
|
const char *cReplayControl::LastReplayed(void)
|
||||||
{
|
{
|
||||||
return fileName;
|
return fileName;
|
||||||
|
17
menu.h
17
menu.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menu.h 1.20 2001/07/28 13:59:29 kls Exp $
|
* $Id: menu.h 1.21 2001/08/02 14:53:29 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MENU_H
|
#ifndef _MENU_H
|
||||||
@ -19,6 +19,8 @@
|
|||||||
class cMenuMain : public cOsdMenu {
|
class cMenuMain : public cOsdMenu {
|
||||||
private:
|
private:
|
||||||
time_t lastActivity;
|
time_t lastActivity;
|
||||||
|
int digit;
|
||||||
|
const char *hk(const char *s);
|
||||||
public:
|
public:
|
||||||
cMenuMain(bool Replaying);
|
cMenuMain(bool Replaying);
|
||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
@ -39,6 +41,16 @@ public:
|
|||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class cMenuDVD : public cOsdMenu {
|
||||||
|
private:
|
||||||
|
cDVD *dvd;//XXX member really necessary???
|
||||||
|
eOSState Play(void);
|
||||||
|
eOSState Eject(void);
|
||||||
|
public:
|
||||||
|
cMenuDVD(void);
|
||||||
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
|
};
|
||||||
|
|
||||||
class cMenuRecordings : public cOsdMenu {
|
class cMenuRecordings : public cOsdMenu {
|
||||||
private:
|
private:
|
||||||
cRecordings Recordings;
|
cRecordings Recordings;
|
||||||
@ -88,6 +100,8 @@ private:
|
|||||||
void Show(int Seconds = 0);
|
void Show(int Seconds = 0);
|
||||||
void Hide(void);
|
void Hide(void);
|
||||||
static char *fileName;
|
static char *fileName;
|
||||||
|
static cDVD *dvd;//XXX member really necessary???
|
||||||
|
static int titleid;//XXX
|
||||||
static char *title;
|
static char *title;
|
||||||
bool ShowProgress(bool Initial);
|
bool ShowProgress(bool Initial);
|
||||||
void MarkToggle(void);
|
void MarkToggle(void);
|
||||||
@ -101,6 +115,7 @@ public:
|
|||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
bool Visible(void) { return visible; }
|
bool Visible(void) { return visible; }
|
||||||
static void SetRecording(const char *FileName, const char *Title);
|
static void SetRecording(const char *FileName, const char *Title);
|
||||||
|
static void SetDVD(cDVD *DVD, int Title);//XXX
|
||||||
static const char *LastReplayed(void);
|
static const char *LastReplayed(void);
|
||||||
static void ClearLastReplayed(const char *FileName);
|
static void ClearLastReplayed(const char *FileName);
|
||||||
};
|
};
|
||||||
|
3
osd.c
3
osd.c
@ -4,11 +4,10 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: osd.c 1.16 2001/02/24 16:26:11 kls Exp $
|
* $Id: osd.c 1.17 2001/08/02 14:18:17 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "osd.h"
|
#include "osd.h"
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
7
osd.h
7
osd.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: osd.h 1.22 2001/07/27 11:33:30 kls Exp $
|
* $Id: osd.h 1.23 2001/08/02 13:48:34 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __OSD_H
|
#ifndef __OSD_H
|
||||||
@ -27,6 +27,7 @@ enum eOSState { osUnknown,
|
|||||||
osCommands,
|
osCommands,
|
||||||
osRecord,
|
osRecord,
|
||||||
osReplay,
|
osReplay,
|
||||||
|
osDVD,
|
||||||
osStopRecord,
|
osStopRecord,
|
||||||
osStopReplay,
|
osStopReplay,
|
||||||
osCancelEdit,
|
osCancelEdit,
|
||||||
@ -55,7 +56,7 @@ public:
|
|||||||
virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||||
virtual void Set(void) {}
|
virtual void Set(void) {}
|
||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
class cOsdBase {
|
class cOsdBase {
|
||||||
protected:
|
protected:
|
||||||
@ -67,7 +68,7 @@ public:
|
|||||||
int Height(void) { return Interface->Height(); }
|
int Height(void) { return Interface->Height(); }
|
||||||
bool NeedsFastResponse(void) { return needsFastResponse; }
|
bool NeedsFastResponse(void) { return needsFastResponse; }
|
||||||
virtual eOSState ProcessKey(eKeys Key) = 0;
|
virtual eOSState ProcessKey(eKeys Key) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class cOsdMenu : public cOsdBase, public cList<cOsdItem> {
|
class cOsdMenu : public cOsdBase, public cList<cOsdItem> {
|
||||||
private:
|
private:
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Parts of this file were inspired by the 'ringbuffy.c' from the
|
* Parts of this file were inspired by the 'ringbuffy.c' from the
|
||||||
* LinuxDVB driver (see linuxtv.org).
|
* LinuxDVB driver (see linuxtv.org).
|
||||||
*
|
*
|
||||||
* $Id: ringbuffer.c 1.2 2001/05/20 11:58:08 kls Exp $
|
* $Id: ringbuffer.c 1.3 2001/08/02 13:48:38 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
@ -69,9 +69,8 @@ int cRingBuffer::Available(void)
|
|||||||
{
|
{
|
||||||
mutex.Lock();
|
mutex.Lock();
|
||||||
int diff = head - tail;
|
int diff = head - tail;
|
||||||
int cont = (diff >= 0) ? diff : size + diff;
|
|
||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
return cont;
|
return (diff >= 0) ? diff : size + diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cRingBuffer::Clear(void)
|
void cRingBuffer::Clear(void)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: ringbuffer.h 1.2 2001/05/20 11:56:44 kls Exp $
|
* $Id: ringbuffer.h 1.3 2001/08/02 13:48:42 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RINGBUFFER_H
|
#ifndef __RINGBUFFER_H
|
||||||
@ -33,6 +33,7 @@ protected:
|
|||||||
void Lock(void) { mutex.Lock(); }
|
void Lock(void) { mutex.Lock(); }
|
||||||
void Unlock(void) { mutex.Unlock(); }
|
void Unlock(void) { mutex.Unlock(); }
|
||||||
int Available(void);
|
int Available(void);
|
||||||
|
int Free(void) { return size - Available() - 1; }
|
||||||
bool Busy(void) { return busy; }
|
bool Busy(void) { return busy; }
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
// Immediately clears the ring buffer.
|
// Immediately clears the ring buffer.
|
||||||
|
37
thread.c
37
thread.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: thread.c 1.9 2001/06/27 11:34:41 kls Exp $
|
* $Id: thread.c 1.10 2001/08/02 13:48:45 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
@ -14,6 +14,40 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
|
// --- cCondVar --------------------------------------------------------------
|
||||||
|
|
||||||
|
cCondVar::cCondVar(void)
|
||||||
|
{
|
||||||
|
pthread_cond_init(&cond, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
cCondVar::~cCondVar()
|
||||||
|
{
|
||||||
|
pthread_cond_destroy(&cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cCondVar::Wait(cMutex &_mutex)
|
||||||
|
{
|
||||||
|
return pthread_cond_wait(&cond, &_mutex.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool cCondVar::TimedWait(cMutex &_mutex, unsigned long tmout)
|
||||||
|
{
|
||||||
|
return pthread_cond_timedwait(&cond, &_mutex.mutex, tmout);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cCondVar::Broadcast(void)
|
||||||
|
{
|
||||||
|
pthread_cond_broadcast(&cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cCondVar::Signal(void)
|
||||||
|
{
|
||||||
|
pthread_cond_signal(&cond);
|
||||||
|
}
|
||||||
|
|
||||||
// --- cMutex ----------------------------------------------------------------
|
// --- cMutex ----------------------------------------------------------------
|
||||||
|
|
||||||
cMutex::cMutex(void)
|
cMutex::cMutex(void)
|
||||||
@ -85,6 +119,7 @@ bool cThread::Start(void)
|
|||||||
running = true;
|
running = true;
|
||||||
parentPid = getpid();
|
parentPid = getpid();
|
||||||
pthread_create(&thread, NULL, (void *(*) (void *))&StartThread, (void *)this);
|
pthread_create(&thread, NULL, (void *(*) (void *))&StartThread, (void *)this);
|
||||||
|
pthread_setschedparam(thread, SCHED_RR, 0);
|
||||||
usleep(10000); // otherwise calling Active() immediately after Start() causes a "pure virtual method called" error
|
usleep(10000); // otherwise calling Active() immediately after Start() causes a "pure virtual method called" error
|
||||||
}
|
}
|
||||||
return true; //XXX return value of pthread_create()???
|
return true; //XXX return value of pthread_create()???
|
||||||
|
17
thread.h
17
thread.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: thread.h 1.6 2001/06/27 11:22:04 kls Exp $
|
* $Id: thread.h 1.7 2001/08/02 13:48:48 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __THREAD_H
|
#ifndef __THREAD_H
|
||||||
@ -13,7 +13,22 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
class cMutex;
|
||||||
|
|
||||||
|
class cCondVar {
|
||||||
|
private:
|
||||||
|
pthread_cond_t cond;
|
||||||
|
public:
|
||||||
|
cCondVar(void);
|
||||||
|
~cCondVar();
|
||||||
|
bool Wait(cMutex &_mutex);
|
||||||
|
//bool TimedWait(cMutex &_mutex, unsigned long tmout);
|
||||||
|
void Broadcast(void);
|
||||||
|
void Signal(void);
|
||||||
|
};
|
||||||
|
|
||||||
class cMutex {
|
class cMutex {
|
||||||
|
friend class cCondVar;
|
||||||
private:
|
private:
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pid_t lockingPid;
|
pid_t lockingPid;
|
||||||
|
14
vdr.c
14
vdr.c
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||||
*
|
*
|
||||||
* $Id: vdr.c 1.58 2001/06/23 12:29:41 kls Exp $
|
* $Id: vdr.c 1.59 2001/08/02 13:48:51 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -31,6 +31,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "dvbapi.h"
|
#include "dvbapi.h"
|
||||||
|
#include "dvd.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@ -85,6 +86,7 @@ int main(int argc, char *argv[])
|
|||||||
{ "log", required_argument, NULL, 'l' },
|
{ "log", required_argument, NULL, 'l' },
|
||||||
{ "port", required_argument, NULL, 'p' },
|
{ "port", required_argument, NULL, 'p' },
|
||||||
{ "video", required_argument, NULL, 'v' },
|
{ "video", required_argument, NULL, 'v' },
|
||||||
|
{ "dvd", required_argument, NULL, 'V' },
|
||||||
{ "watchdog", required_argument, NULL, 'w' },
|
{ "watchdog", required_argument, NULL, 'w' },
|
||||||
{ "terminal", required_argument, NULL, 't' },
|
{ "terminal", required_argument, NULL, 't' },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
@ -92,7 +94,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
int c;
|
int c;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
while ((c = getopt_long(argc, argv, "a:c:dD:hl:p:v:w:t:", long_options, &option_index)) != -1) {
|
while ((c = getopt_long(argc, argv, "a:c:dD:hl:p:v:V:w:t:", long_options, &option_index)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'a': cDvbApi::SetAudioCommand(optarg);
|
case 'a': cDvbApi::SetAudioCommand(optarg);
|
||||||
break;
|
break;
|
||||||
@ -124,6 +126,7 @@ int main(int argc, char *argv[])
|
|||||||
" -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n"
|
" -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n"
|
||||||
" 0 turns off SVDRP\n"
|
" 0 turns off SVDRP\n"
|
||||||
" -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
|
" -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
|
||||||
|
" -V DEV, --dvd=DEV use DEV as the DVD device (default: %s)\n"
|
||||||
" -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
|
" -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
|
||||||
" seconds (default: %d); '0' disables the watchdog\n"
|
" seconds (default: %d); '0' disables the watchdog\n"
|
||||||
" -t TTY, --terminal=TTY controlling tty\n"
|
" -t TTY, --terminal=TTY controlling tty\n"
|
||||||
@ -131,6 +134,7 @@ int main(int argc, char *argv[])
|
|||||||
"Report bugs to <vdr-bugs@cadsoft.de>\n",
|
"Report bugs to <vdr-bugs@cadsoft.de>\n",
|
||||||
DEFAULTSVDRPPORT,
|
DEFAULTSVDRPPORT,
|
||||||
VideoDirectory,
|
VideoDirectory,
|
||||||
|
cDVD::DeviceName(),
|
||||||
DEFAULTWATCHDOG
|
DEFAULTWATCHDOG
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
@ -158,6 +162,8 @@ int main(int argc, char *argv[])
|
|||||||
while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/')
|
while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/')
|
||||||
optarg[strlen(optarg) - 1] = 0;
|
optarg[strlen(optarg) - 1] = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'V': cDVD::SetDeviceName(optarg);
|
||||||
|
break;
|
||||||
case 'w': if (isnumber(optarg)) {
|
case 'w': if (isnumber(optarg)) {
|
||||||
int t = atoi(optarg);
|
int t = atoi(optarg);
|
||||||
if (t >= 0) {
|
if (t >= 0) {
|
||||||
@ -324,6 +330,10 @@ int main(int argc, char *argv[])
|
|||||||
DELETENULL(ReplayControl);
|
DELETENULL(ReplayControl);
|
||||||
ReplayControl = new cReplayControl;
|
ReplayControl = new cReplayControl;
|
||||||
break;
|
break;
|
||||||
|
case osDVD: DELETENULL(Menu);
|
||||||
|
DELETENULL(ReplayControl);
|
||||||
|
Menu = new cMenuDVD;
|
||||||
|
break;
|
||||||
case osStopReplay:
|
case osStopReplay:
|
||||||
DELETENULL(*Interact);
|
DELETENULL(*Interact);
|
||||||
DELETENULL(ReplayControl);
|
DELETENULL(ReplayControl);
|
||||||
|
Loading…
Reference in New Issue
Block a user