Created
March 5, 2026 02:22
-
-
Save patrickdk77/330dd3f593696d103e831c4c1d78d1f9 to your computer and use it in GitHub Desktop.
DS2 codec
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/libavcodec/Makefile b/libavcodec/Makefile | |
| index fb22541f8d..3b98da18a3 100644 | |
| --- a/libavcodec/Makefile | |
| +++ b/libavcodec/Makefile | |
| @@ -344,6 +344,7 @@ OBJS-$(CONFIG_DSD_MSBF_PLANAR_DECODER) += dsddec.o dsd.o | |
| OBJS-$(CONFIG_DSICINAUDIO_DECODER) += dsicinaudio.o | |
| OBJS-$(CONFIG_DSICINVIDEO_DECODER) += dsicinvideo.o | |
| OBJS-$(CONFIG_DSS_SP_DECODER) += dss_sp.o | |
| +OBJS-$(CONFIG_DS2_DECODER) += ds2.o | |
| OBJS-$(CONFIG_DST_DECODER) += dstdec.o dsd.o | |
| OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o | |
| OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsubenc.o | |
| diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c | |
| index f5ec2e01e8..c7a19029b6 100644 | |
| --- a/libavcodec/allcodecs.c | |
| +++ b/libavcodec/allcodecs.c | |
| @@ -461,6 +461,7 @@ extern const FFCodec ff_dca_decoder; | |
| extern const FFCodec ff_dfpwm_encoder; | |
| extern const FFCodec ff_dfpwm_decoder; | |
| extern const FFCodec ff_dolby_e_decoder; | |
| +extern const FFCodec ff_ds2_decoder; | |
| extern const FFCodec ff_dsd_lsbf_decoder; | |
| extern const FFCodec ff_dsd_msbf_decoder; | |
| extern const FFCodec ff_dsd_lsbf_planar_decoder; | |
| diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c | |
| index a065556e51..2ea12d440c 100644 | |
| --- a/libavcodec/codec_desc.c | |
| +++ b/libavcodec/codec_desc.c | |
| @@ -3495,6 +3495,13 @@ static const AVCodecDescriptor codec_descriptors[] = { | |
| .long_name = NULL_IF_CONFIG_SMALL("G.728"), | |
| .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, | |
| }, | |
| + { | |
| + .id = AV_CODEC_ID_DS2, | |
| + .type = AVMEDIA_TYPE_AUDIO, | |
| + .name = "ds2", | |
| + .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard Pro (DS2)"), | |
| + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, | |
| + }, | |
| /* subtitle codecs */ | |
| { | |
| diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h | |
| index c4842e61ff..97ad9b200b 100644 | |
| --- a/libavcodec/codec_id.h | |
| +++ b/libavcodec/codec_id.h | |
| @@ -556,6 +556,7 @@ enum AVCodecID { | |
| AV_CODEC_ID_QOA, | |
| AV_CODEC_ID_LC3, | |
| AV_CODEC_ID_G728, | |
| + AV_CODEC_ID_DS2, | |
| /* subtitle codecs */ | |
| AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. | |
| diff --git a/libavcodec/ds2.c b/libavcodec/ds2.c | |
| new file mode 100644 | |
| index 0000000000..fc6e1a473a | |
| --- /dev/null | |
| +++ b/libavcodec/ds2.c | |
| @@ -0,0 +1,982 @@ | |
| +/* | |
| + * Digital Speech Standard Pro (DS2) audio decoder | |
| + */ | |
| + | |
| +/** | |
| + * @file | |
| + * DS2 (DSS Pro) CELP audio decoder | |
| + * | |
| + * Supports two modes: | |
| + * - SP mode: 12000 Hz, 14 reflection coefficients, 4×72-sample subframes, | |
| + * C(72,7) combinatorial codebook, 328-bit frames | |
| + * - QP mode: 16000 Hz, 16 reflection coefficients, 4×64-sample subframes, | |
| + * C(64,11) combinatorial codebook, 448-bit frames | |
| + * | |
| + * Based on technical documentation from FFmpeg trac ticket #6091. | |
| + * | |
| + */ | |
| + | |
| +#include <math.h> | |
| + | |
| +#include "libavutil/channel_layout.h" | |
| +#include "libavutil/common.h" | |
| +#include "libavutil/mem_internal.h" | |
| + | |
| +#include "avcodec.h" | |
| +#include "codec_internal.h" | |
| +#include "decode.h" | |
| +#include "get_bits.h" | |
| + | |
| +/* ---- Constants ---- */ | |
| + | |
| +#define DS2_SUBFRAMES 4 | |
| + | |
| +/* SP mode */ | |
| +#define DS2_SP_FORMAT 0 | |
| +#define DS2_SP_SAMPLE_RATE 12000 | |
| +#define DS2_SP_SUBFRAME_SIZE 72 | |
| +#define DS2_SP_FRAME_SAMPLES (DS2_SP_SUBFRAME_SIZE * DS2_SUBFRAMES) /* 288 */ | |
| +#define DS2_SP_FRAME_SIZE 42 /* bytes per packet from demuxer */ | |
| +#define DS2_SP_FRAME_BITS 328 | |
| +#define DS2_SP_NUM_REFL 14 | |
| +#define DS2_SP_NUM_PULSES 7 | |
| +#define DS2_SP_COMB_N 72 | |
| +#define DS2_SP_COMB_BITS 31 | |
| +#define DS2_SP_PITCH_MIN 36 | |
| +#define DS2_SP_PITCH_MAX 186 | |
| +#define DS2_SP_PITCH_RANGE (DS2_SP_PITCH_MAX - DS2_SP_PITCH_MIN + 1) /* 151 */ | |
| +#define DS2_SP_DELTA_RANGE 48 | |
| + | |
| +/* QP mode */ | |
| +#define DS2_QP_FORMAT 6 | |
| +#define DS2_QP_SAMPLE_RATE 16000 | |
| +#define DS2_QP_SUBFRAME_SIZE 64 | |
| +#define DS2_QP_FRAME_SAMPLES (DS2_QP_SUBFRAME_SIZE * DS2_SUBFRAMES) /* 256 */ | |
| +#define DS2_QP_FRAME_SIZE 56 /* bytes per packet from demuxer */ | |
| +#define DS2_QP_FRAME_BITS 448 | |
| +#define DS2_QP_NUM_REFL 16 | |
| +#define DS2_QP_NUM_PULSES 11 | |
| +#define DS2_QP_COMB_N 64 | |
| +#define DS2_QP_COMB_BITS 40 | |
| +#define DS2_QP_PITCH_MIN 45 | |
| +#define DS2_QP_PITCH_MAX 300 | |
| + | |
| +/* Maximum values across both modes */ | |
| +#define DS2_MAX_REFL 16 | |
| +#define DS2_MAX_PULSES 11 | |
| +#define DS2_MAX_SUBFRAME 72 | |
| +#define DS2_MAX_FRAME_SIZE 56 | |
| +#define DS2_MAX_FRAME_SAMPLES 288 | |
| +#define DS2_MAX_PITCH 300 | |
| + | |
| +/* ---- Quantization tables (from DssDecoder.dll via hirparak/dss-codec) ---- */ | |
| + | |
| +static const int ds2_sp_refl_cb_sizes[DS2_SP_NUM_REFL] = { | |
| + 32, 32, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8}; | |
| + | |
| +static const int ds2_sp_refl_bits[DS2_SP_NUM_REFL] = {5, 5, 4, 4, 4, 4, 4, | |
| + 4, 3, 3, 3, 3, 3, 3}; | |
| + | |
| +static const double ds2_sp_refl_cb[DS2_SP_NUM_REFL][32] = { | |
| + /* codebook 0: 32 entries (5 bits) */ | |
| + { | |
| + -0.996490, -0.994475, -0.992274, -0.989923, -0.986979, -0.983156, -0.978457, -0.972945, | |
| + -0.966344, -0.958182, -0.948497, -0.937621, -0.924654, -0.909824, -0.892581, -0.871936, | |
| + -0.844538, -0.806867, -0.752737, -0.685593, -0.593059, -0.492327, -0.372867, -0.237519, | |
| + -0.086492, 0.055505, 0.199702, 0.343643, 0.489801, 0.617074, 0.756038, 0.858146, | |
| + }, | |
| + /* codebook 1: 32 entries (5 bits) */ | |
| + { | |
| + -0.839325, -0.747960, -0.630004, -0.533942, -0.432954, -0.344139, -0.256963, -0.170734, | |
| + -0.091958, -0.019039, 0.052224, 0.118393, 0.178355, 0.237254, 0.297215, 0.353767, | |
| + 0.407842, 0.454813, 0.501291, 0.546275, 0.587472, 0.628223, 0.665388, 0.702075, | |
| + 0.736745, 0.770544, 0.801860, 0.833128, 0.865451, 0.892610, 0.919122, 0.951620, | |
| + }, | |
| + /* codebook 2: 16 entries (4 bits) */ | |
| + { | |
| + -0.849219, -0.738774, -0.639128, -0.542629, -0.452975, -0.361563, -0.276658, -0.192157, | |
| + -0.111700, -0.027783, 0.058547, 0.153345, 0.250940, 0.355490, 0.460400, 0.562225, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 3: 16 entries (4 bits) */ | |
| + { | |
| + -0.522694, -0.365443, -0.252366, -0.156340, -0.070064, 0.005590, 0.076400, 0.143647, | |
| + 0.207452, 0.272966, 0.337068, 0.404016, 0.473864, 0.556895, 0.644373, 0.756378, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 4: 16 entries (4 bits) */ | |
| + { | |
| + -0.657867, -0.527349, -0.435986, -0.355341, -0.282832, -0.216282, -0.150720, -0.086403, | |
| + -0.021073, 0.042924, 0.107923, 0.174593, 0.247943, 0.325844, 0.418718, 0.541122, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 5: 16 entries (4 bits) */ | |
| + { | |
| + -0.458685, -0.316669, -0.214667, -0.132058, -0.057968, 0.011117, 0.075008, 0.135795, | |
| + 0.195985, 0.255549, 0.316590, 0.381044, 0.449024, 0.518693, 0.598949, 0.700509, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 6: 16 entries (4 bits) */ | |
| + { | |
| + -0.493011, -0.377254, -0.295947, -0.227659, -0.160461, -0.102515, -0.047207, 0.006675, | |
| + 0.058478, 0.109825, 0.161717, 0.213432, 0.273530, 0.342584, 0.418583, 0.518245, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 7: 16 entries (4 bits) */ | |
| + { | |
| + -0.449880, -0.300532, -0.211206, -0.141852, -0.084516, -0.032514, 0.015220, 0.063580, | |
| + 0.110867, 0.159284, 0.209267, 0.261856, 0.317693, 0.386711, 0.474887, 0.613438, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 8: 8 entries (3 bits) */ | |
| + { | |
| + -0.338720, -0.214064, -0.117633, -0.031277, 0.051259, 0.138659, 0.238260, 0.364144, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 9: 8 entries (3 bits) */ | |
| + { | |
| + -0.276501, -0.139475, -0.042152, 0.043296, 0.123121, 0.205330, 0.301063, 0.431780, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 10: 8 entries (3 bits) */ | |
| + { | |
| + -0.379946, -0.243693, -0.140265, -0.052907, 0.029329, 0.110756, 0.209498, 0.340020, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 11: 8 entries (3 bits) */ | |
| + { | |
| + -0.361040, -0.225940, -0.122373, -0.033455, 0.049012, 0.130947, 0.225389, 0.350395, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 12: 8 entries (3 bits) */ | |
| + { | |
| + -0.409067, -0.282274, -0.182942, -0.101077, -0.027164, 0.048645, 0.136240, 0.250184, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 13: 8 entries (3 bits) */ | |
| + { | |
| + -0.342987, -0.220337, -0.123291, -0.042908, 0.029633, 0.101349, 0.183289, 0.295929, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| +}; | |
| + | |
| +/* SP pitch gain: 32 entries (5-bit) at VA 0x1004CF90 */ | |
| +static const double ds2_sp_pitch_gain[32] = { | |
| + 0.049805, 0.112793, 0.175781, 0.238281, 0.301270, 0.364258, 0.427246, 0.490234, | |
| + 0.553223, 0.615723, 0.678711, 0.741699, 0.804688, 0.867676, 0.930176, 0.993164, | |
| + 1.056152, 1.119141, 1.182129, 1.245117, 1.307617, 1.370605, 1.433594, 1.496582, | |
| + 1.559570, 1.622559, 1.685059, 1.748047, 1.811035, 1.874023, 1.937012, 2.000000, | |
| +}; | |
| + | |
| +/* SP excitation gain: 64 entries (6-bit) at VA 0x1004DF80 */ | |
| +static const double ds2_sp_exc_gain[64] = { | |
| + 0, 4, 8, 13, 17, 22, 26, 31, 35, 40, | |
| + 44, 48, 53, 58, 63, 69, 76, 83, 91, 99, | |
| + 109, 119, 130, 142, 155, 170, 185, 203, 222, 242, | |
| + 265, 290, 317, 346, 378, 414, 452, 494, 540, 591, | |
| + 646, 706, 771, 843, 922, 1007, 1101, 1204, 1316, 1438, | |
| + 1572, 1719, 1879, 2053, 2244, 2453, 2682, 2931, 3204, 3502, | |
| + 3828, 4184, 4574, 5000, | |
| +}; | |
| + | |
| +/* SP pulse amplitude: 8 entries (3-bit) at VA 0x1004EF70 */ | |
| +static const double ds2_sp_pulse_amp[8] = { | |
| + -0.951599, -0.679718, -0.407837, -0.135956, 0.135956, 0.407837, 0.679718, 0.951599, | |
| +}; | |
| + | |
| +static const int ds2_qp_refl_cb_sizes[DS2_QP_NUM_REFL] = { | |
| + 128, 128, 64, 64, 32, 32, 32, 32, 32, 16, 16, 16, 16, 8, 8, 8}; | |
| + | |
| +static const int ds2_qp_refl_bits[DS2_QP_NUM_REFL] = {7, 7, 6, 6, 5, 5, 5, 5, | |
| + 5, 4, 4, 4, 4, 3, 3, 3}; | |
| + | |
| +static const double ds2_qp_refl_cb[DS2_QP_NUM_REFL][128] = { | |
| + /* codebook 0: 128 entries (7 bits) */ | |
| + { | |
| + -0.998625, -0.997661, -0.996599, -0.995565, -0.994543, -0.993491, -0.992388, -0.991230, | |
| + -0.990023, -0.988774, -0.987484, -0.986156, -0.984772, -0.983336, -0.981849, -0.980306, | |
| + -0.978698, -0.977036, -0.975326, -0.973557, -0.971730, -0.969817, -0.967830, -0.965767, | |
| + -0.963617, -0.961358, -0.958986, -0.956532, -0.953973, -0.951304, -0.948517, -0.945580, | |
| + -0.942517, -0.939292, -0.935919, -0.932382, -0.928627, -0.924691, -0.920565, -0.916220, | |
| + -0.911672, -0.906908, -0.901909, -0.896650, -0.891154, -0.885378, -0.879331, -0.873053, | |
| + -0.866477, -0.859569, -0.852378, -0.844956, -0.837212, -0.829238, -0.820897, -0.812297, | |
| + -0.803364, -0.794100, -0.784575, -0.774668, -0.764433, -0.753852, -0.743069, -0.731850, | |
| + -0.720141, -0.707839, -0.695049, -0.681824, -0.668123, -0.654004, -0.639425, -0.624341, | |
| + -0.608685, -0.592626, -0.575763, -0.558598, -0.540993, -0.522682, -0.503785, -0.484018, | |
| + -0.464117, -0.443659, -0.422977, -0.401829, -0.380472, -0.358738, -0.337042, -0.315200, | |
| + -0.292816, -0.269804, -0.246840, -0.223819, -0.200574, -0.176809, -0.152793, -0.128330, | |
| + -0.103243, -0.078064, -0.052123, -0.025868, 0.000503, 0.032633, 0.065304, 0.098316, | |
| + 0.130992, 0.163876, 0.197635, 0.231801, 0.266734, 0.300840, 0.334427, 0.368009, | |
| + 0.401816, 0.434818, 0.467743, 0.500737, 0.533103, 0.566143, 0.599057, 0.631503, | |
| + 0.663943, 0.696451, 0.729205, 0.762428, 0.795263, 0.829412, 0.866713, 0.910326, | |
| + }, | |
| + /* codebook 1: 128 entries (7 bits) */ | |
| + { | |
| + -0.865978, -0.801655, -0.751056, -0.707177, -0.667018, -0.629630, -0.593900, -0.560117, | |
| + -0.529107, -0.501775, -0.477329, -0.455520, -0.435556, -0.417392, -0.400411, -0.384593, | |
| + -0.369412, -0.354722, -0.340281, -0.325968, -0.311620, -0.297118, -0.282403, -0.267459, | |
| + -0.252110, -0.236259, -0.220193, -0.204047, -0.187752, -0.171201, -0.154549, -0.137981, | |
| + -0.121239, -0.104248, -0.087220, -0.070049, -0.052835, -0.035604, -0.018345, -0.000989, | |
| + 0.013341, 0.027691, 0.042198, 0.056848, 0.071551, 0.086361, 0.101247, 0.116275, | |
| + 0.131413, 0.146502, 0.161609, 0.176928, 0.192267, 0.207584, 0.223239, 0.238667, | |
| + 0.254052, 0.269405, 0.284689, 0.299822, 0.314990, 0.329889, 0.344662, 0.359470, | |
| + 0.374096, 0.388852, 0.403536, 0.418103, 0.432528, 0.446911, 0.458448, 0.469920, | |
| + 0.481265, 0.492536, 0.503570, 0.514533, 0.525419, 0.536162, 0.546901, 0.557527, | |
| + 0.568032, 0.578325, 0.588612, 0.598800, 0.608864, 0.618771, 0.628586, 0.638361, | |
| + 0.648084, 0.657681, 0.667230, 0.676748, 0.686191, 0.695626, 0.704918, 0.714094, | |
| + 0.723141, 0.731977, 0.740690, 0.749332, 0.757905, 0.766358, 0.774776, 0.783032, | |
| + 0.791223, 0.799327, 0.807335, 0.815280, 0.823165, 0.830937, 0.838722, 0.846445, | |
| + 0.854029, 0.861501, 0.868889, 0.876232, 0.883524, 0.890694, 0.897831, 0.904884, | |
| + 0.911897, 0.918903, 0.925945, 0.933146, 0.940675, 0.948957, 0.958556, 0.970177, | |
| + }, | |
| + /* codebook 2: 64 entries (6 bits) */ | |
| + { | |
| + -0.878298, -0.824992, -0.785065, -0.751040, -0.720251, -0.691891, -0.665181, -0.639786, | |
| + -0.615369, -0.591615, -0.568490, -0.545987, -0.523926, -0.502127, -0.480738, -0.459651, | |
| + -0.438673, -0.417783, -0.397059, -0.376483, -0.356260, -0.336413, -0.316974, -0.297934, | |
| + -0.279303, -0.260922, -0.242715, -0.224602, -0.206399, -0.187986, -0.169304, -0.150560, | |
| + -0.131689, -0.112776, -0.093829, -0.075030, -0.056117, -0.037019, -0.017915, 0.001264, | |
| + 0.021956, 0.042920, 0.064134, 0.085565, 0.107325, 0.129603, 0.152421, 0.175870, | |
| + 0.200016, 0.224916, 0.250766, 0.277574, 0.305699, 0.335073, 0.365590, 0.397311, | |
| + 0.430498, 0.464755, 0.497242, 0.530987, 0.567807, 0.615533, 0.677622, 0.762953, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 3: 64 entries (6 bits) */ | |
| + { | |
| + -0.678301, -0.588324, -0.523419, -0.470562, -0.425205, -0.385018, -0.348530, -0.315336, | |
| + -0.284695, -0.255877, -0.228880, -0.203303, -0.178950, -0.155800, -0.133970, -0.113249, | |
| + -0.093394, -0.074330, -0.055708, -0.037490, -0.019546, -0.001718, 0.014539, 0.030657, | |
| + 0.046714, 0.062695, 0.078703, 0.094689, 0.110696, 0.126759, 0.142860, 0.158969, | |
| + 0.175153, 0.191502, 0.207935, 0.224561, 0.241260, 0.258094, 0.275189, 0.292432, | |
| + 0.307372, 0.322453, 0.337726, 0.353530, 0.369788, 0.386586, 0.403952, 0.421954, | |
| + 0.440682, 0.460037, 0.479761, 0.499936, 0.520518, 0.541623, 0.563237, 0.585518, | |
| + 0.608755, 0.633034, 0.658787, 0.686368, 0.716820, 0.751347, 0.793450, 0.849863, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 4: 32 entries (5 bits) */ | |
| + { | |
| + -0.686023, -0.590033, -0.522276, -0.465560, -0.415065, -0.369456, -0.327471, -0.288452, | |
| + -0.251939, -0.217904, -0.185983, -0.156000, -0.127564, -0.100169, -0.073317, -0.046679, | |
| + -0.019984, 0.006884, 0.037317, 0.068121, 0.099353, 0.130970, 0.161878, 0.193212, | |
| + 0.225897, 0.261272, 0.301182, 0.346922, 0.398337, 0.456646, 0.526277, 0.619643, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 5: 32 entries (5 bits) */ | |
| + { | |
| + -0.527743, -0.424492, -0.352527, -0.294102, -0.243637, -0.198721, -0.158197, -0.121422, | |
| + -0.087780, -0.056634, -0.027564, -0.000057, 0.026333, 0.051882, 0.076891, 0.101336, | |
| + 0.125239, 0.148710, 0.172091, 0.195743, 0.219951, 0.245374, 0.272629, 0.302507, | |
| + 0.334789, 0.369369, 0.406797, 0.447397, 0.492493, 0.544022, 0.606679, 0.691200, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 6: 32 entries (5 bits) */ | |
| + { | |
| + -0.601019, -0.499809, -0.428508, -0.371195, -0.322148, -0.278716, -0.239398, -0.203176, | |
| + -0.169584, -0.138470, -0.109415, -0.081977, -0.055553, -0.029524, -0.004614, 0.018106, | |
| + 0.040751, 0.063446, 0.086254, 0.109317, 0.133064, 0.157973, 0.184758, 0.214130, | |
| + 0.246852, 0.282811, 0.321893, 0.364386, 0.410975, 0.463634, 0.526693, 0.612511, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 7: 32 entries (5 bits) */ | |
| + { | |
| + -0.463201, -0.366113, -0.303086, -0.254487, -0.213519, -0.177606, -0.145363, -0.116011, | |
| + -0.089086, -0.064222, -0.040750, -0.018223, 0.003277, 0.025510, 0.047020, 0.068122, | |
| + 0.089031, 0.110133, 0.131587, 0.153729, 0.176942, 0.201557, 0.228146, 0.257067, | |
| + 0.288453, 0.322393, 0.358870, 0.398374, 0.442175, 0.492459, 0.552623, 0.636121, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 8: 32 entries (5 bits) */ | |
| + { | |
| + -0.509145, -0.418749, -0.358351, -0.311239, -0.271890, -0.237792, -0.207221, -0.179058, | |
| + -0.152976, -0.128516, -0.105298, -0.083077, -0.061680, -0.040969, -0.020397, -0.000226, | |
| + 0.019619, 0.039298, 0.059006, 0.079040, 0.099577, 0.120854, 0.143279, 0.167235, | |
| + 0.193205, 0.221520, 0.252694, 0.287225, 0.326977, 0.373768, 0.432608, 0.518828, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 9: 16 entries (4 bits) */ | |
| + { | |
| + -0.332855, -0.231237, -0.159643, -0.102155, -0.053615, -0.012904, 0.021531, 0.054450, | |
| + 0.086850, 0.119913, 0.155290, 0.195219, 0.242115, 0.298426, 0.369436, 0.471129, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 10: 16 entries (4 bits) */ | |
| + { | |
| + -0.376020, -0.278260, -0.212618, -0.160891, -0.117377, -0.079398, -0.045440, -0.014884, | |
| + 0.014776, 0.047827, 0.082969, 0.122059, 0.167728, 0.222525, 0.291029, 0.387801, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 11: 16 entries (4 bits) */ | |
| + { | |
| + -0.342852, -0.248889, -0.183868, -0.132410, -0.089601, -0.053097, -0.020720, 0.011049, | |
| + 0.043759, 0.076197, 0.109914, 0.146761, 0.189409, 0.241277, 0.308095, 0.407348, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 12: 16 entries (4 bits) */ | |
| + { | |
| + -0.400796, -0.311045, -0.247060, -0.195185, -0.150538, -0.111345, -0.076540, -0.045016, | |
| + -0.015976, 0.012588, 0.044647, 0.079552, 0.119807, 0.169084, 0.233651, 0.331372, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 13: 8 entries (3 bits) */ | |
| + { | |
| + -0.287554, -0.179259, -0.098331, -0.034309, 0.021941, 0.079790, 0.147318, 0.251007, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 14: 8 entries (3 bits) */ | |
| + { | |
| + -0.307008, -0.197848, -0.118523, -0.056781, -0.004304, 0.048868, 0.113937, 0.212073, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| + /* codebook 15: 8 entries (3 bits) */ | |
| + { | |
| + -0.269441, -0.164866, -0.087872, -0.028712, 0.024066, 0.079931, 0.147043, 0.246413, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, | |
| + }, | |
| +}; | |
| + | |
| +/* QP pitch gain: 64 entries (6-bit) at VA 0x1004BA10 */ | |
| +static const double ds2_qp_pitch_gain[64] = { | |
| + 0.004913, 0.056367, 0.102669, 0.145092, 0.184286, 0.220170, 0.252640, 0.281841, | |
| + 0.308202, 0.332237, 0.354531, 0.375491, 0.395460, 0.414675, 0.433337, 0.451622, | |
| + 0.469648, 0.487486, 0.505255, 0.523016, 0.540824, 0.558764, 0.576890, 0.595276, | |
| + 0.613963, 0.632917, 0.652245, 0.671900, 0.691902, 0.712322, 0.733015, 0.753909, | |
| + 0.774967, 0.796116, 0.817233, 0.838156, 0.858900, 0.879346, 0.899405, 0.919040, | |
| + 0.938366, 0.957462, 0.976668, 0.996526, 1.017693, 1.041066, 1.066882, 1.095219, | |
| + 1.126158, 1.159959, 1.196753, 1.236515, 1.279487, 1.325996, 1.376201, 1.429902, | |
| + 1.487140, 1.548301, 1.613491, 1.682657, 1.755914, 1.833605, 1.914886, 1.999406, | |
| +}; | |
| + | |
| +/* QP excitation gain: 64 entries (6-bit) at VA 0x1004BC10 */ | |
| +static const double ds2_qp_exc_gain[64] = { | |
| + 3.928000, 7.069000, 10.993000, 16.465000, 23.856000, 32.753000, 42.893000, 54.076000, | |
| + 66.160000, 79.016000, 92.493000, 106.558000, 121.106000, 136.128000, 151.663000, 167.700000, | |
| + 184.251000, 201.424000, 219.212000, 237.740000, 257.014000, 277.134000, 298.164000, 320.054000, | |
| + 342.913000, 366.849000, 391.851000, 418.102000, 445.564000, 474.334000, 504.476000, 536.280000, | |
| + 569.771000, 604.926000, 642.050000, 681.112000, 722.397000, 766.071000, 812.234000, 861.189000, | |
| + 913.161000, 968.356000, 1027.220000, 1089.687000, 1156.595000, 1228.228000, 1305.279000, 1387.811000, | |
| + 1476.597000, 1572.636000, 1675.856000, 1789.017000, 1911.832000, 2045.863000, 2194.195000, 2360.133000, | |
| + 2545.084000, 2752.592000, 2991.921000, 3271.340000, 3603.855000, 4004.808000, 4476.587000, 4970.296000, | |
| +}; | |
| + | |
| +/* QP pulse amplitude: 8 entries (3-bit) at VA 0x1004BE10 */ | |
| +static const double ds2_qp_pulse_amp[8] = { | |
| + -0.921705, -0.628998, -0.397315, -0.140886, 0.206959, 0.433678, 0.652927, 0.931249, | |
| +}; | |
| + | |
| +/* De-emphasis coefficient for QP mode */ | |
| +#define DS2_QP_DEEMPH_COEFF 0.1 | |
| + | |
| +/* ---- Combinatorial number computation ---- */ | |
| + | |
| +/** | |
| + * Compute binomial coefficient C(n, k) = n! / (k! * (n-k)!) | |
| + */ | |
| +static uint64_t ds2_comb(int n, int k) { | |
| + uint64_t result = 1; | |
| + int i; | |
| + | |
| + if (k > n) | |
| + return 0; | |
| + if (k > n - k) | |
| + k = n - k; | |
| + | |
| + for (i = 0; i < k; i++) { | |
| + result *= (n - i); | |
| + result /= (i + 1); | |
| + } | |
| + | |
| + return result; | |
| +} | |
| + | |
| +/** | |
| + * Decode a combinatorial index into k positions from {0..n-1}. | |
| + * Positions are returned in DESCENDING order (do NOT sort). | |
| + */ | |
| +static void ds2_decode_combinatorial(uint64_t index, int n, int k, | |
| + int *positions) { | |
| + uint64_t remaining = index; | |
| + int i, v; | |
| + | |
| + for (i = k; i >= 1; i--) { | |
| + v = i - 1; | |
| + while (v + 1 < n && ds2_comb(v + 1, i) <= remaining) | |
| + v++; | |
| + positions[k - i] = v; | |
| + remaining -= ds2_comb(v, i); | |
| + } | |
| +} | |
| + | |
| +/* ---- Codec context ---- */ | |
| + | |
| +typedef struct DS2Subframe { | |
| + double pitch_gain; | |
| + int pitch_lag; | |
| + double exc_gain; | |
| + uint64_t cb_index; /* combinatorial codebook index */ | |
| + int pulse_positions[DS2_MAX_PULSES]; | |
| + int pulse_indices[DS2_MAX_PULSES]; /* indices into pulse_amp table */ | |
| +} DS2Subframe; | |
| + | |
| +typedef struct DS2Context { | |
| + AVCodecContext *avctx; | |
| + int mode; /* DS2_SP_FORMAT or DS2_QP_FORMAT */ | |
| + int num_refl; /* 14 (SP) or 16 (QP) */ | |
| + int subframe_size; /* 72 (SP) or 64 (QP) */ | |
| + int frame_samples; /* 288 (SP) or 256 (QP) */ | |
| + int num_pulses; /* 7 (SP) or 11 (QP) */ | |
| + int comb_n; /* 72 (SP) or 64 (QP) */ | |
| + int frame_size; /* bytes: 42 (SP) or 56 (QP) */ | |
| + | |
| + /* Per-frame decoded parameters */ | |
| + double refl_coeffs[DS2_MAX_REFL]; | |
| + DS2Subframe sf[DS2_SUBFRAMES]; | |
| + | |
| + /* Persistent state */ | |
| + double lattice_state[DS2_MAX_REFL]; /* lattice filter state */ | |
| + double pitch_memory[DS2_MAX_PITCH + DS2_MAX_SUBFRAME]; | |
| + int pitch_mem_len; | |
| + double deemph_state; /* QP de-emphasis */ | |
| + | |
| + /* Working buffers */ | |
| + double excitation[DS2_MAX_SUBFRAME]; | |
| + double fixed_exc[DS2_MAX_SUBFRAME]; | |
| + double adaptive_exc[DS2_MAX_SUBFRAME]; | |
| + double synth_out[DS2_MAX_SUBFRAME]; | |
| + | |
| + DECLARE_ALIGNED(16, uint8_t, bits) | |
| + [DS2_MAX_FRAME_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; | |
| +} DS2Context; | |
| + | |
| +/* ---- Bitstream unpacking ---- */ | |
| + | |
| +/** | |
| + * Prepare bitstream: swap bytes within 16-bit LE words for MSB-first reading. | |
| + * This is the same bit order as FFmpeg's existing DSS SP reader. | |
| + */ | |
| +static void ds2_swap_bytes(DS2Context *p, const uint8_t *src, int size) { | |
| + int i; | |
| + for (i = 0; i < size - 1; i += 2) { | |
| + p->bits[i] = src[i + 1]; | |
| + p->bits[i + 1] = src[i]; | |
| + } | |
| + if (size & 1) | |
| + p->bits[size - 1] = src[size - 1]; | |
| +} | |
| + | |
| +static void ds2_sp_unpack_frame(DS2Context *p, const uint8_t *src) { | |
| + GetBitContext gb; | |
| + int i, sf_idx; | |
| + uint32_t combined_pitch; | |
| + | |
| + ds2_swap_bytes(p, src, DS2_SP_FRAME_SIZE); | |
| + init_get_bits(&gb, p->bits, DS2_SP_FRAME_BITS); | |
| + | |
| + /* Reflection coefficients */ | |
| + for (i = 0; i < DS2_SP_NUM_REFL; i++) { | |
| + int idx = get_bits(&gb, ds2_sp_refl_bits[i]); | |
| + p->refl_coeffs[i] = ds2_sp_refl_cb[i][idx]; | |
| + } | |
| + | |
| + /* Per-subframe parameters */ | |
| + for (sf_idx = 0; sf_idx < DS2_SUBFRAMES; sf_idx++) { | |
| + DS2Subframe *sf = &p->sf[sf_idx]; | |
| + int pg_idx, eg_idx; | |
| + | |
| + pg_idx = get_bits(&gb, 5); | |
| + sf->cb_index = get_bits_long(&gb, DS2_SP_COMB_BITS); | |
| + eg_idx = get_bits(&gb, 6); | |
| + | |
| + sf->pitch_gain = ds2_sp_pitch_gain[pg_idx]; | |
| + sf->exc_gain = ds2_sp_exc_gain[eg_idx]; | |
| + | |
| + for (i = 0; i < DS2_SP_NUM_PULSES; i++) | |
| + sf->pulse_indices[i] = get_bits(&gb, 3); | |
| + | |
| + /* Decode combinatorial pulse positions */ | |
| + ds2_decode_combinatorial(sf->cb_index, DS2_SP_COMB_N, DS2_SP_NUM_PULSES, | |
| + sf->pulse_positions); | |
| + } | |
| + | |
| + /* Combined pitch: 24 bits encoding 4 pitch lags */ | |
| + combined_pitch = get_bits_long(&gb, 24); | |
| + | |
| + p->sf[0].pitch_lag = (combined_pitch % DS2_SP_PITCH_RANGE) + DS2_SP_PITCH_MIN; | |
| + combined_pitch /= DS2_SP_PITCH_RANGE; | |
| + | |
| + for (i = 1; i < DS2_SUBFRAMES - 1; i++) { | |
| + p->sf[i].pitch_lag = combined_pitch % DS2_SP_DELTA_RANGE; | |
| + combined_pitch /= DS2_SP_DELTA_RANGE; | |
| + } | |
| + if (combined_pitch > DS2_SP_DELTA_RANGE - 1) | |
| + combined_pitch = 0; | |
| + p->sf[DS2_SUBFRAMES - 1].pitch_lag = combined_pitch; | |
| + | |
| + /* Convert delta pitch lags to absolute */ | |
| + { | |
| + int prev_pitch = p->sf[0].pitch_lag; | |
| + int half_delta = DS2_SP_DELTA_RANGE / 2 - 1; /* 23 */ | |
| + | |
| + for (i = 1; i < DS2_SUBFRAMES; i++) { | |
| + int base; | |
| + if (prev_pitch > DS2_SP_PITCH_MAX - half_delta) | |
| + base = DS2_SP_PITCH_MAX - half_delta - half_delta; | |
| + else if (prev_pitch >= DS2_SP_PITCH_MIN + half_delta) | |
| + base = prev_pitch - half_delta; | |
| + else | |
| + base = DS2_SP_PITCH_MIN; | |
| + | |
| + p->sf[i].pitch_lag += base; | |
| + prev_pitch = p->sf[i].pitch_lag; | |
| + } | |
| + } | |
| +} | |
| + | |
| +static void ds2_qp_unpack_frame(DS2Context *p, const uint8_t *src) { | |
| + GetBitContext gb; | |
| + int i, sf_idx; | |
| + | |
| + ds2_swap_bytes(p, src, DS2_QP_FRAME_SIZE); | |
| + init_get_bits(&gb, p->bits, DS2_QP_FRAME_BITS); | |
| + | |
| + /* Reflection coefficients */ | |
| + for (i = 0; i < DS2_QP_NUM_REFL; i++) { | |
| + int idx = get_bits(&gb, ds2_qp_refl_bits[i]); | |
| + p->refl_coeffs[i] = ds2_qp_refl_cb[i][idx]; | |
| + } | |
| + | |
| + /* Per-subframe parameters */ | |
| + for (sf_idx = 0; sf_idx < DS2_SUBFRAMES; sf_idx++) { | |
| + DS2Subframe *sf = &p->sf[sf_idx]; | |
| + int pg_idx, eg_idx; | |
| + | |
| + /* QP: pitch is 8 bits direct per subframe */ | |
| + sf->pitch_lag = get_bits(&gb, 8) + DS2_QP_PITCH_MIN; | |
| + | |
| + pg_idx = get_bits(&gb, 6); | |
| + sf->cb_index = get_bits64(&gb, DS2_QP_COMB_BITS); | |
| + eg_idx = get_bits(&gb, 6); | |
| + | |
| + sf->pitch_gain = ds2_qp_pitch_gain[pg_idx]; | |
| + sf->exc_gain = ds2_qp_exc_gain[eg_idx]; | |
| + | |
| + for (i = 0; i < DS2_QP_NUM_PULSES; i++) | |
| + sf->pulse_indices[i] = get_bits(&gb, 3); | |
| + | |
| + /* Decode combinatorial pulse positions */ | |
| + ds2_decode_combinatorial(sf->cb_index, DS2_QP_COMB_N, DS2_QP_NUM_PULSES, | |
| + sf->pulse_positions); | |
| + } | |
| +} | |
| + | |
| +/** | |
| + * Generate adaptive excitation by repeating pitch memory at pitch period. | |
| + */ | |
| +static void ds2_gen_adaptive_exc(DS2Context *p, int pitch_lag, | |
| + int subframe_size) { | |
| + int i; | |
| + int mem_end = p->pitch_mem_len; | |
| + | |
| + for (i = 0; i < subframe_size; i++) { | |
| + if (pitch_lag < subframe_size) { | |
| + p->adaptive_exc[i] = | |
| + p->pitch_memory[mem_end - pitch_lag + (i % pitch_lag)]; | |
| + } else { | |
| + p->adaptive_exc[i] = p->pitch_memory[mem_end - pitch_lag + i]; | |
| + } | |
| + } | |
| +} | |
| + | |
| +/** | |
| + * Generate fixed (sparse pulse) excitation. | |
| + */ | |
| +static void ds2_gen_fixed_exc(DS2Context *p, int sf_idx, int subframe_size) { | |
| + int i; | |
| + DS2Subframe *sf = &p->sf[sf_idx]; | |
| + const double *pulse_amp; | |
| + int num_pulses; | |
| + | |
| + if (p->mode == DS2_SP_FORMAT) { | |
| + pulse_amp = ds2_sp_pulse_amp; | |
| + num_pulses = DS2_SP_NUM_PULSES; | |
| + } else { | |
| + pulse_amp = ds2_qp_pulse_amp; | |
| + num_pulses = DS2_QP_NUM_PULSES; | |
| + } | |
| + | |
| + memset(p->fixed_exc, 0, sizeof(double) * subframe_size); | |
| + | |
| + for (i = 0; i < num_pulses; i++) { | |
| + int pos = sf->pulse_positions[i]; | |
| + if (pos >= 0 && pos < subframe_size) | |
| + p->fixed_exc[pos] += pulse_amp[sf->pulse_indices[i]] * sf->exc_gain; | |
| + } | |
| +} | |
| + | |
| +/** | |
| + * Combine adaptive and fixed excitation. | |
| + */ | |
| +static void ds2_gen_excitation(DS2Context *p, int sf_idx, int subframe_size) { | |
| + int i; | |
| + DS2Subframe *sf = &p->sf[sf_idx]; | |
| + | |
| + for (i = 0; i < subframe_size; i++) | |
| + p->excitation[i] = sf->pitch_gain * p->adaptive_exc[i] + p->fixed_exc[i]; | |
| +} | |
| + | |
| +/** | |
| + * Lattice synthesis filter. | |
| + * Normalized form with reflection coefficients. | |
| + */ | |
| +static void ds2_lattice_filter(DS2Context *p, int subframe_size) { | |
| + int n, k; | |
| + int num_refl = p->num_refl; | |
| + | |
| + for (n = 0; n < subframe_size; n++) { | |
| + double acc = p->excitation[n] - | |
| + p->lattice_state[num_refl - 1] * p->refl_coeffs[num_refl - 1]; | |
| + | |
| + for (k = num_refl - 2; k >= 0; k--) { | |
| + acc -= p->lattice_state[k] * p->refl_coeffs[k]; | |
| + p->lattice_state[k + 1] = p->refl_coeffs[k] * acc + p->lattice_state[k]; | |
| + } | |
| + | |
| + p->lattice_state[0] = acc; | |
| + p->synth_out[n] = acc; | |
| + } | |
| +} | |
| + | |
| +/** | |
| + * Update pitch memory with new excitation. | |
| + */ | |
| +static void ds2_update_pitch_memory(DS2Context *p, int subframe_size) { | |
| + int max_pitch = | |
| + (p->mode == DS2_SP_FORMAT) ? DS2_SP_PITCH_MAX : DS2_QP_PITCH_MAX; | |
| + int total = max_pitch + subframe_size; | |
| + int i; | |
| + | |
| + /* Shift old data */ | |
| + for (i = 0; i < max_pitch; i++) | |
| + p->pitch_memory[i] = p->pitch_memory[i + subframe_size]; | |
| + | |
| + /* Append new excitation */ | |
| + for (i = 0; i < subframe_size; i++) | |
| + p->pitch_memory[max_pitch + i] = p->excitation[i]; | |
| + | |
| + p->pitch_mem_len = total; | |
| +} | |
| + | |
| +/** | |
| + * QP de-emphasis: y[n] = x[n] + 0.1 * y[n-1] | |
| + */ | |
| +static void ds2_qp_deemphasis(DS2Context *p, double *samples, int size) { | |
| + int i; | |
| + double prev = p->deemph_state; | |
| + | |
| + for (i = 0; i < size; i++) { | |
| + samples[i] = samples[i] + DS2_QP_DEEMPH_COEFF * prev; | |
| + prev = samples[i]; | |
| + } | |
| + | |
| + p->deemph_state = prev; | |
| +} | |
| + | |
| +/* ---- Main decode entry points ---- */ | |
| + | |
| +static av_cold int ds2_decode_init(AVCodecContext *avctx) { | |
| + DS2Context *p = avctx->priv_data; | |
| + p->avctx = avctx; | |
| + | |
| + avctx->sample_fmt = AV_SAMPLE_FMT_S16; | |
| + av_channel_layout_uninit(&avctx->ch_layout); | |
| + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; | |
| + | |
| + /* Determine mode from codec_tag set by demuxer */ | |
| + if (avctx->codec_tag == DS2_QP_FORMAT) { | |
| + p->mode = DS2_QP_FORMAT; | |
| + p->num_refl = DS2_QP_NUM_REFL; | |
| + p->subframe_size = DS2_QP_SUBFRAME_SIZE; | |
| + p->frame_samples = DS2_QP_FRAME_SAMPLES; | |
| + p->num_pulses = DS2_QP_NUM_PULSES; | |
| + p->comb_n = DS2_QP_COMB_N; | |
| + p->frame_size = DS2_QP_FRAME_SIZE; | |
| + avctx->sample_rate = DS2_QP_SAMPLE_RATE; | |
| + } else { | |
| + /* Default to SP */ | |
| + p->mode = DS2_SP_FORMAT; | |
| + p->num_refl = DS2_SP_NUM_REFL; | |
| + p->subframe_size = DS2_SP_SUBFRAME_SIZE; | |
| + p->frame_samples = DS2_SP_FRAME_SAMPLES; | |
| + p->num_pulses = DS2_SP_NUM_PULSES; | |
| + p->comb_n = DS2_SP_COMB_N; | |
| + p->frame_size = DS2_SP_FRAME_SIZE; | |
| + avctx->sample_rate = DS2_SP_SAMPLE_RATE; | |
| + } | |
| + | |
| + /* Initialize pitch memory */ | |
| + memset(p->pitch_memory, 0, sizeof(p->pitch_memory)); | |
| + p->pitch_mem_len = (p->mode == DS2_SP_FORMAT) | |
| + ? DS2_SP_PITCH_MAX + DS2_SP_SUBFRAME_SIZE | |
| + : DS2_QP_PITCH_MAX + DS2_QP_SUBFRAME_SIZE; | |
| + | |
| + memset(p->lattice_state, 0, sizeof(p->lattice_state)); | |
| + p->deemph_state = 0.0; | |
| + | |
| + return 0; | |
| +} | |
| + | |
| +static int ds2_decode_frame(AVCodecContext *avctx, AVFrame *frame, | |
| + int *got_frame_ptr, AVPacket *avpkt) { | |
| + DS2Context *p = avctx->priv_data; | |
| + const uint8_t *buf = avpkt->data; | |
| + int buf_size = avpkt->size; | |
| + int16_t *out; | |
| + int ret, j, i; | |
| + | |
| + if (buf_size < p->frame_size) { | |
| + if (buf_size) | |
| + av_log(avctx, AV_LOG_WARNING, | |
| + "Expected %d bytes, got %d - skipping packet.\n", p->frame_size, | |
| + buf_size); | |
| + *got_frame_ptr = 0; | |
| + return AVERROR_INVALIDDATA; | |
| + } | |
| + | |
| + frame->nb_samples = p->frame_samples; | |
| + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) | |
| + return ret; | |
| + | |
| + out = (int16_t *)frame->data[0]; | |
| + | |
| + /* Unpack frame parameters from bitstream */ | |
| + if (p->mode == DS2_SP_FORMAT) | |
| + ds2_sp_unpack_frame(p, buf); | |
| + else | |
| + ds2_qp_unpack_frame(p, buf); | |
| + | |
| + /* Decode each subframe */ | |
| + for (j = 0; j < DS2_SUBFRAMES; j++) { | |
| + /* Generate adaptive excitation from pitch memory */ | |
| + ds2_gen_adaptive_exc(p, p->sf[j].pitch_lag, p->subframe_size); | |
| + | |
| + /* Generate fixed excitation from pulse codebook */ | |
| + ds2_gen_fixed_exc(p, j, p->subframe_size); | |
| + | |
| + /* Combine: excitation = pitch_gain * adaptive + fixed */ | |
| + ds2_gen_excitation(p, j, p->subframe_size); | |
| + | |
| + /* Update pitch memory */ | |
| + ds2_update_pitch_memory(p, p->subframe_size); | |
| + | |
| + /* Lattice synthesis filter */ | |
| + ds2_lattice_filter(p, p->subframe_size); | |
| + | |
| + /* QP de-emphasis */ | |
| + if (p->mode == DS2_QP_FORMAT) | |
| + ds2_qp_deemphasis(p, p->synth_out, p->subframe_size); | |
| + | |
| + /* Convert to int16 output */ | |
| + for (i = 0; i < p->subframe_size; i++) { | |
| + double sample = p->synth_out[i]; | |
| + if (sample > 32767.0) | |
| + sample = 32767.0; | |
| + else if (sample < -32768.0) | |
| + sample = -32768.0; | |
| + out[j * p->subframe_size + i] = (int16_t)lrint(sample); | |
| + } | |
| + } | |
| + | |
| + *got_frame_ptr = 1; | |
| + return p->frame_size; | |
| +} | |
| + | |
| +const FFCodec ff_ds2_decoder = { | |
| + .p.name = "ds2", | |
| + CODEC_LONG_NAME("Digital Speech Standard Pro (DS2)"), | |
| + .p.type = AVMEDIA_TYPE_AUDIO, | |
| + .p.id = AV_CODEC_ID_DS2, | |
| + .priv_data_size = sizeof(DS2Context), | |
| + .init = ds2_decode_init, | |
| + FF_CODEC_DECODE_CB(ds2_decode_frame), | |
| + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, | |
| +}; | |
| diff --git a/libavformat/Makefile b/libavformat/Makefile | |
| index ab5551a735..ed872b56ff 100644 | |
| --- a/libavformat/Makefile | |
| +++ b/libavformat/Makefile | |
| @@ -195,6 +195,7 @@ OBJS-$(CONFIG_DNXHD_MUXER) += rawenc.o | |
| OBJS-$(CONFIG_DSF_DEMUXER) += dsfdec.o | |
| OBJS-$(CONFIG_DSICIN_DEMUXER) += dsicin.o | |
| OBJS-$(CONFIG_DSS_DEMUXER) += dss.o | |
| +OBJS-$(CONFIG_DS2_DEMUXER) += ds2.o | |
| OBJS-$(CONFIG_DTSHD_DEMUXER) += dtshddec.o | |
| OBJS-$(CONFIG_DTS_DEMUXER) += dtsdec.o rawdec.o | |
| OBJS-$(CONFIG_DTS_MUXER) += rawenc.o | |
| diff --git a/libavformat/allformats.c b/libavformat/allformats.c | |
| index e39eab8e85..7db5389eea 100644 | |
| --- a/libavformat/allformats.c | |
| +++ b/libavformat/allformats.c | |
| @@ -148,6 +148,7 @@ extern const FFInputFormat ff_dsf_demuxer; | |
| extern const FFInputFormat ff_dsicin_demuxer; | |
| extern const FFInputFormat ff_dss_demuxer; | |
| extern const FFInputFormat ff_dts_demuxer; | |
| +extern const FFInputFormat ff_ds2_demuxer; | |
| extern const FFOutputFormat ff_dts_muxer; | |
| extern const FFInputFormat ff_dtshd_demuxer; | |
| extern const FFInputFormat ff_dv_demuxer; | |
| diff --git a/libavformat/ds2.c b/libavformat/ds2.c | |
| new file mode 100644 | |
| index 0000000000..9c0326c0cb | |
| --- /dev/null | |
| +++ b/libavformat/ds2.c | |
| @@ -0,0 +1,369 @@ | |
| +/* | |
| + * Digital Speech Standard Pro (DS2) demuxer | |
| + */ | |
| + | |
| +/** | |
| + * @file | |
| + * DS2 (DSS Pro) demuxer | |
| + * | |
| + * DS2 is an evolution of the Digital Speech Standard (DSS) format used by | |
| + * Olympus dictation recorders. It supports two codec modes: | |
| + * - SP (Standard Play): 12000 Hz, CELP with C(72,7) codebook | |
| + * - QP (Quality Play): 16000 Hz, CELP with C(64,11) codebook | |
| + * | |
| + * Format details from FFmpeg trac ticket #6091. | |
| + */ | |
| + | |
| +#include "libavutil/channel_layout.h" | |
| +#include "libavutil/intreadwrite.h" | |
| +#include "libavutil/mem.h" | |
| + | |
| +#include "avformat.h" | |
| +#include "demux.h" | |
| +#include "internal.h" | |
| + | |
| +#define DS2_HEADER_SIZE 0x600 /* 1536 bytes */ | |
| +#define DS2_BLOCK_SIZE 512 | |
| +#define DS2_AUDIO_BLOCK_HEADER_SIZE 6 | |
| +#define DS2_BLOCK_PAYLOAD_SIZE (DS2_BLOCK_SIZE - DS2_AUDIO_BLOCK_HEADER_SIZE) | |
| + | |
| +#define DS2_FORMAT_SP 0 /* Standard Play, 12000 Hz */ | |
| +#define DS2_FORMAT_QP 6 /* Quality Play, 16000 Hz */ | |
| + | |
| +#define DS2_SP_FRAME_SIZE 42 /* SP: 328 bits ~ 41 bytes, padded to 42 */ | |
| +#define DS2_SP_FRAME_BITS 328 | |
| +#define DS2_SP_SAMPLES_PER_FRAME 288 /* 72 samples * 4 subframes */ | |
| +#define DS2_SP_SAMPLE_RATE 12000 | |
| + | |
| +#define DS2_QP_FRAME_BITS 448 | |
| +#define DS2_QP_FRAME_SIZE 56 /* 448 bits = 56 bytes */ | |
| +#define DS2_QP_SAMPLES_PER_FRAME 256 /* 64 samples * 4 subframes */ | |
| +#define DS2_QP_SAMPLE_RATE 16000 | |
| + | |
| +/* Metadata offsets (same layout as DSS) */ | |
| +#define DS2_HEAD_OFFSET_AUTHOR 0xc | |
| +#define DS2_AUTHOR_SIZE 16 | |
| +#define DS2_HEAD_OFFSET_START_TIME 0x26 | |
| +#define DS2_HEAD_OFFSET_END_TIME 0x32 | |
| +#define DS2_TIME_SIZE 12 | |
| +#define DS2_HEAD_OFFSET_COMMENT 0x31e | |
| +#define DS2_COMMENT_SIZE 64 | |
| + | |
| +typedef struct DS2DemuxContext { | |
| + int format_type; /* DS2_FORMAT_SP or DS2_FORMAT_QP */ | |
| + int counter; /* bytes remaining in current block payload */ | |
| + int swap; /* SP byte-swap state */ | |
| + int ds2_sp_swap_byte; /* saved swap byte for SP mode */ | |
| + int total_frames; /* total frame count from block headers */ | |
| + int frames_read; /* frames read so far */ | |
| +} DS2DemuxContext; | |
| + | |
| +static int ds2_probe(const AVProbeData *p) { | |
| + if (AV_RL32(p->buf) != MKTAG(0x3, 'd', 's', '2')) | |
| + return 0; | |
| + | |
| + return AVPROBE_SCORE_MAX; | |
| +} | |
| + | |
| +static int ds2_read_metadata_date(AVFormatContext *s, unsigned int offset, | |
| + const char *key) { | |
| + AVIOContext *pb = s->pb; | |
| + char datetime[64], string[DS2_TIME_SIZE + 1] = {0}; | |
| + int y, month, d, h, minute, sec; | |
| + int ret; | |
| + | |
| + avio_seek(pb, offset, SEEK_SET); | |
| + | |
| + ret = avio_read(pb, string, DS2_TIME_SIZE); | |
| + if (ret < DS2_TIME_SIZE) | |
| + return ret < 0 ? ret : AVERROR_EOF; | |
| + | |
| + if (sscanf(string, "%2d%2d%2d%2d%2d%2d", &y, &month, &d, &h, &minute, &sec) != | |
| + 6) | |
| + return AVERROR_INVALIDDATA; | |
| + | |
| + snprintf(datetime, sizeof(datetime), "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d", | |
| + y + 2000, month, d, h, minute, sec); | |
| + return av_dict_set(&s->metadata, key, datetime, 0); | |
| +} | |
| + | |
| +static int ds2_read_metadata_string(AVFormatContext *s, unsigned int offset, | |
| + unsigned int size, const char *key) { | |
| + AVIOContext *pb = s->pb; | |
| + char *value; | |
| + int ret; | |
| + | |
| + avio_seek(pb, offset, SEEK_SET); | |
| + | |
| + value = av_mallocz(size + 1); | |
| + if (!value) | |
| + return AVERROR(ENOMEM); | |
| + | |
| + ret = avio_read(pb, value, size); | |
| + if (ret < size) { | |
| + av_free(value); | |
| + return ret < 0 ? ret : AVERROR_EOF; | |
| + } | |
| + | |
| + return av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); | |
| +} | |
| + | |
| +static int ds2_read_header(AVFormatContext *s) { | |
| + DS2DemuxContext *ctx = s->priv_data; | |
| + AVIOContext *pb = s->pb; | |
| + AVStream *st; | |
| + uint8_t block_header[DS2_AUDIO_BLOCK_HEADER_SIZE]; | |
| + int ret; | |
| + int64_t ret64; | |
| + | |
| + st = avformat_new_stream(s, NULL); | |
| + if (!st) | |
| + return AVERROR(ENOMEM); | |
| + | |
| + /* Read metadata */ | |
| + ret = ds2_read_metadata_string(s, DS2_HEAD_OFFSET_AUTHOR, DS2_AUTHOR_SIZE, | |
| + "author"); | |
| + if (ret) | |
| + return ret; | |
| + | |
| + ret = ds2_read_metadata_date(s, DS2_HEAD_OFFSET_END_TIME, "date"); | |
| + if (ret) | |
| + return ret; | |
| + | |
| + ret = ds2_read_metadata_string(s, DS2_HEAD_OFFSET_COMMENT, DS2_COMMENT_SIZE, | |
| + "comment"); | |
| + if (ret) | |
| + return ret; | |
| + | |
| + /* Seek to first audio block to read its header */ | |
| + if ((ret64 = avio_seek(pb, DS2_HEADER_SIZE, SEEK_SET)) < 0) | |
| + return (int)ret64; | |
| + | |
| + ret = avio_read(pb, block_header, DS2_AUDIO_BLOCK_HEADER_SIZE); | |
| + if (ret < DS2_AUDIO_BLOCK_HEADER_SIZE) | |
| + return ret < 0 ? ret : AVERROR_EOF; | |
| + | |
| + /* byte4 of block header is the format type */ | |
| + ctx->format_type = block_header[4]; | |
| + | |
| + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; | |
| + st->codecpar->codec_id = AV_CODEC_ID_DS2; | |
| + st->codecpar->codec_tag = ctx->format_type; | |
| + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; | |
| + | |
| + if (ctx->format_type == DS2_FORMAT_SP) { | |
| + st->codecpar->sample_rate = DS2_SP_SAMPLE_RATE; | |
| + } else if (ctx->format_type == DS2_FORMAT_QP) { | |
| + st->codecpar->sample_rate = DS2_QP_SAMPLE_RATE; | |
| + } else { | |
| + avpriv_request_sample(s, "DS2 format type %d", ctx->format_type); | |
| + return AVERROR_PATCHWELCOME; | |
| + } | |
| + | |
| + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); | |
| + st->start_time = 0; | |
| + | |
| + /* Initialize SP swap state from bit 7 of first block's byte0 */ | |
| + ctx->swap = !!(block_header[0] & 0x80); | |
| + ctx->ds2_sp_swap_byte = -1; | |
| + | |
| + /* Seek back to start of first block payload (after the header we just read) | |
| + */ | |
| + ctx->counter = DS2_BLOCK_PAYLOAD_SIZE; | |
| + | |
| + return 0; | |
| +} | |
| + | |
| +static void ds2_skip_audio_header(AVFormatContext *s) { | |
| + DS2DemuxContext *ctx = s->priv_data; | |
| + | |
| + avio_skip(s->pb, DS2_AUDIO_BLOCK_HEADER_SIZE); | |
| + ctx->counter = DS2_BLOCK_PAYLOAD_SIZE; | |
| +} | |
| + | |
| +/** | |
| + * SP byte-swap logic. | |
| + * | |
| + * DS2 SP uses an alternating byte-swap scheme similar to DSS: | |
| + * - No-swap frame: read 42 bytes, save byte[40] as swap_byte, zero byte[40] | |
| + * - Swap frame: read 40 bytes into pkt[3..], shift even-indexed bytes: | |
| + * pkt[i] = pkt[i+4] for i in 0..40 step 2, set pkt[1] = swap_byte | |
| + * - Zero pkt[40] before decoding, toggle swap state | |
| + */ | |
| +static void ds2_sp_byte_swap(DS2DemuxContext *ctx, uint8_t *data) { | |
| + int i; | |
| + | |
| + if (ctx->swap) { | |
| + for (i = 0; i < DS2_SP_FRAME_SIZE - 2; i += 2) | |
| + data[i] = data[i + 4]; | |
| + | |
| + data[DS2_SP_FRAME_SIZE] = 0; | |
| + data[1] = ctx->ds2_sp_swap_byte; | |
| + } else { | |
| + ctx->ds2_sp_swap_byte = data[DS2_SP_FRAME_SIZE - 2]; | |
| + } | |
| + | |
| + /* Ensure byte 40 is always 0 */ | |
| + data[DS2_SP_FRAME_SIZE - 2] = 0; | |
| + ctx->swap ^= 1; | |
| +} | |
| + | |
| +static int ds2_sp_read_packet(AVFormatContext *s, AVPacket *pkt) { | |
| + DS2DemuxContext *ctx = s->priv_data; | |
| + int read_size, ret, offset = 0, buff_offset = 0; | |
| + int64_t pos = avio_tell(s->pb); | |
| + | |
| + if (ctx->counter == 0) | |
| + ds2_skip_audio_header(s); | |
| + | |
| + if (ctx->swap) { | |
| + read_size = DS2_SP_FRAME_SIZE - 2; /* 40 bytes */ | |
| + buff_offset = 3; | |
| + } else { | |
| + read_size = DS2_SP_FRAME_SIZE; /* 42 bytes */ | |
| + } | |
| + | |
| + ret = av_new_packet(pkt, DS2_SP_FRAME_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); | |
| + if (ret < 0) | |
| + return ret; | |
| + pkt->size = DS2_SP_FRAME_SIZE; | |
| + | |
| + pkt->duration = DS2_SP_SAMPLES_PER_FRAME; | |
| + pkt->pos = pos; | |
| + pkt->stream_index = 0; | |
| + | |
| + if (ctx->counter < read_size) { | |
| + ret = avio_read(s->pb, pkt->data + buff_offset, ctx->counter); | |
| + if (ret < ctx->counter) | |
| + goto error_eof; | |
| + | |
| + offset = ctx->counter; | |
| + ds2_skip_audio_header(s); | |
| + } | |
| + ctx->counter -= (read_size - offset); | |
| + | |
| + ret = avio_read(s->pb, pkt->data + offset + buff_offset, read_size - offset); | |
| + if (ret < read_size - offset) | |
| + goto error_eof; | |
| + | |
| + ds2_sp_byte_swap(ctx, pkt->data); | |
| + | |
| + if (ctx->ds2_sp_swap_byte < 0) | |
| + return AVERROR(EAGAIN); | |
| + | |
| + return 0; | |
| + | |
| +error_eof: | |
| + return ret < 0 ? ret : AVERROR_EOF; | |
| +} | |
| + | |
| +static int ds2_qp_read_packet(AVFormatContext *s, AVPacket *pkt) { | |
| + DS2DemuxContext *ctx = s->priv_data; | |
| + int ret, offset = 0; | |
| + int64_t pos = avio_tell(s->pb); | |
| + | |
| + if (ctx->counter == 0) | |
| + ds2_skip_audio_header(s); | |
| + | |
| + ret = av_new_packet(pkt, DS2_QP_FRAME_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); | |
| + if (ret < 0) | |
| + return ret; | |
| + pkt->size = DS2_QP_FRAME_SIZE; | |
| + | |
| + pkt->duration = DS2_QP_SAMPLES_PER_FRAME; | |
| + pkt->pos = pos; | |
| + pkt->stream_index = 0; | |
| + | |
| + /* | |
| + * QP frames are 56 bytes in a continuous bitstream across blocks. | |
| + * Frames can span block boundaries, so we read in pieces if needed. | |
| + */ | |
| + while (offset < DS2_QP_FRAME_SIZE) { | |
| + int to_read = FFMIN(DS2_QP_FRAME_SIZE - offset, ctx->counter); | |
| + if (to_read <= 0) { | |
| + ds2_skip_audio_header(s); | |
| + to_read = FFMIN(DS2_QP_FRAME_SIZE - offset, ctx->counter); | |
| + } | |
| + | |
| + ret = avio_read(s->pb, pkt->data + offset, to_read); | |
| + if (ret < to_read) { | |
| + return ret < 0 ? ret : AVERROR_EOF; | |
| + } | |
| + | |
| + offset += to_read; | |
| + ctx->counter -= to_read; | |
| + } | |
| + | |
| + return 0; | |
| +} | |
| + | |
| +static int ds2_read_packet(AVFormatContext *s, AVPacket *pkt) { | |
| + DS2DemuxContext *ctx = s->priv_data; | |
| + | |
| + if (ctx->format_type == DS2_FORMAT_SP) | |
| + return ds2_sp_read_packet(s, pkt); | |
| + else | |
| + return ds2_qp_read_packet(s, pkt); | |
| +} | |
| + | |
| +static int ds2_read_seek(AVFormatContext *s, int stream_index, | |
| + int64_t timestamp, int flags) { | |
| + DS2DemuxContext *ctx = s->priv_data; | |
| + int64_t ret, seekto; | |
| + uint8_t header[DS2_AUDIO_BLOCK_HEADER_SIZE]; | |
| + int offset; | |
| + | |
| + if (ctx->format_type == DS2_FORMAT_SP) { | |
| + /* SP: 42-byte frames (avg 41 bytes with swap interleaving) */ | |
| + seekto = timestamp / DS2_SP_SAMPLES_PER_FRAME * 41 / | |
| + DS2_BLOCK_PAYLOAD_SIZE * DS2_BLOCK_SIZE; | |
| + } else { | |
| + /* QP: 56-byte frames */ | |
| + seekto = timestamp / DS2_QP_SAMPLES_PER_FRAME * DS2_QP_FRAME_SIZE / | |
| + DS2_BLOCK_PAYLOAD_SIZE * DS2_BLOCK_SIZE; | |
| + } | |
| + | |
| + if (seekto < 0) | |
| + seekto = 0; | |
| + | |
| + seekto += DS2_HEADER_SIZE; | |
| + | |
| + ret = avio_seek(s->pb, seekto, SEEK_SET); | |
| + if (ret < 0) | |
| + return ret; | |
| + | |
| + ret = avio_read(s->pb, header, DS2_AUDIO_BLOCK_HEADER_SIZE); | |
| + if (ret < DS2_AUDIO_BLOCK_HEADER_SIZE) | |
| + return ret < 0 ? ret : AVERROR_EOF; | |
| + | |
| + if (ctx->format_type == DS2_FORMAT_SP) { | |
| + ctx->swap = !!(header[0] & 0x80); | |
| + offset = 2 * header[1] + 2 * ctx->swap; | |
| + if (offset < DS2_AUDIO_BLOCK_HEADER_SIZE) | |
| + return AVERROR_INVALIDDATA; | |
| + if (offset == DS2_AUDIO_BLOCK_HEADER_SIZE) { | |
| + ctx->counter = 0; | |
| + avio_skip(s->pb, -DS2_AUDIO_BLOCK_HEADER_SIZE); | |
| + } else { | |
| + ctx->counter = DS2_BLOCK_SIZE - offset; | |
| + avio_skip(s->pb, offset - DS2_AUDIO_BLOCK_HEADER_SIZE); | |
| + } | |
| + ctx->ds2_sp_swap_byte = -1; | |
| + } else { | |
| + /* QP: just start at block payload boundary */ | |
| + ctx->counter = DS2_BLOCK_PAYLOAD_SIZE; | |
| + } | |
| + | |
| + return 0; | |
| +} | |
| + | |
| +const FFInputFormat ff_ds2_demuxer = { | |
| + .p.name = "ds2", | |
| + .p.long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard Pro (DS2)"), | |
| + .p.extensions = "ds2", | |
| + .priv_data_size = sizeof(DS2DemuxContext), | |
| + .read_probe = ds2_probe, | |
| + .read_header = ds2_read_header, | |
| + .read_packet = ds2_read_packet, | |
| + .read_seek = ds2_read_seek, | |
| +}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment