annotate src/demac/apedec.c @ 2284:d19b53359b24

cleaned up the sndfile wav plugin, currently limiting it ONLY TO WAV PLAYBACK. if somebody is more experienced with it and wants to restore the other formats, go ahead (maybe change the name of the plugin too?).
author mf0102 <0102@gmx.at>
date Wed, 09 Jan 2008 15:41:22 +0100
parents cc5e9ec110a4
children ed6c81bd9016
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2182
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
1 /*
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
2 * Monkey's Audio lossless audio decoder, standalone version
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
3 * Copyright (c) 2007 Benjamin Zores <ben@geexbox.org>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
4 * based upon libdemac from Dave Chapman.
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
5 * Copyright (c) 2007 Eugene Zagidullin <e.asphyx@gmail.com>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
6 * Cleanup libav* depending code, Audacious stuff.
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
7 *
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
8 * This file is part of FFmpeg.
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
9 *
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
10 * FFmpeg is free software; you can redistribute it and/or
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
11 * modify it under the terms of the GNU Lesser General Public
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
12 * License as published by the Free Software Foundation; either
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
13 * version 2.1 of the License, or (at your option) any later version.
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
14 *
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
15 * FFmpeg is distributed in the hope that it will be useful,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
18 * Lesser General Public License for more details.
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
19 *
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
20 * You should have received a copy of the GNU Lesser General Public
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
21 * License along with FFmpeg; if not, write to the Free Software
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
23 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
24
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
25 #include <stdio.h>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
26 #include <stdlib.h>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
27 #include <errno.h>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
28 #include <string.h>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
29 #include <assert.h>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
30
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
31 #include <audacious/vfs.h>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
32 #include <audacious/plugin.h>
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
33
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
34 #include "ape.h"
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
35
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
36 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
37 * @file apedec.c
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
38 * Monkey's Audio lossless audio decoder
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
39 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
40
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
41
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
42 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
43 * Possible compression levels
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
44 * @{
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
45 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
46 enum APECompressionLevel {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
47 COMPRESSION_LEVEL_FAST = 1000,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
48 COMPRESSION_LEVEL_NORMAL = 2000,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
49 COMPRESSION_LEVEL_HIGH = 3000,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
50 COMPRESSION_LEVEL_EXTRA_HIGH = 4000,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
51 COMPRESSION_LEVEL_INSANE = 5000
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
52 };
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
53 /** @} */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
54
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
55
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
56 /** Filter orders depending on compression level */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
57 static const uint16_t ape_filter_orders[5][APE_FILTER_LEVELS] = {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
58 { 0, 0, 0 },
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
59 { 16, 0, 0 },
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
60 { 64, 0, 0 },
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
61 { 32, 256, 0 },
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
62 { 16, 256, 1280 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
63 };
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
64
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
65 /** Filter fraction bits depending on compression level */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
66 static const uint16_t ape_filter_fracbits[5][APE_FILTER_LEVELS] = {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
67 { 0, 0, 0 },
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
68 { 11, 0, 0 },
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
69 { 11, 0, 0 },
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
70 { 10, 13, 0 },
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
71 { 11, 13, 15 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
72 };
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
73
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
74 // TODO: dsputilize
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
75 static inline void vector_add(int16_t * v1, int16_t * v2, int order)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
76 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
77 while (order--)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
78 *v1++ += *v2++;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
79 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
80
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
81 // TODO: dsputilize
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
82 static inline void vector_sub(int16_t * v1, int16_t * v2, int order)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
83 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
84 while (order--)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
85 *v1++ -= *v2++;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
86 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
87
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
88 // TODO: dsputilize
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
89 static inline int32_t scalarproduct(int16_t * v1, int16_t * v2, int order)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
90 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
91 int res = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
92
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
93 while (order--)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
94 res += *v1++ * *v2++;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
95
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
96 return res;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
97 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
98
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
99 int ape_decode_init(APEDecoderContext *s, APEContext *ctx)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
100 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
101 int i;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
102
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
103 if (ctx->bps != 16) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
104 av_log(avctx, AV_LOG_ERROR, "Only 16-bit samples are supported\n");
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
105 return -1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
106 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
107 if (ctx->channels > 2) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
108 av_log(avctx, AV_LOG_ERROR, "Only mono and stereo is supported\n");
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
109 return -1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
110 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
111 s->apectx = ctx;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
112 s->channels = ctx->channels;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
113 s->fileversion = ctx->fileversion;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
114 s->compression_level = ctx->compressiontype;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
115 s->flags = ctx->formatflags;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
116 s->max_packet_size = ctx->max_packet_size; // We will use this value to avoid multiply reallocs. Eugene.
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
117
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
118 av_log(avctx, AV_LOG_DEBUG, "Compression Level: %d - Flags: %d\n", s->compression_level, s->flags);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
119 if (s->compression_level % 1000 || s->compression_level > COMPRESSION_LEVEL_INSANE) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
120 av_log(avctx, AV_LOG_ERROR, "Incorrect compression level %d\n", s->compression_level);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
121 return -1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
122 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
123 s->fset = s->compression_level / 1000 - 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
124 for (i = 0; i < APE_FILTER_LEVELS; i++) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
125 if (!ape_filter_orders[s->fset][i])
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
126 break;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
127 s->filterbuf[i] = malloc((ape_filter_orders[s->fset][i] * 3 + HISTORY_SIZE) * 4);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
128 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
129
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
130 //dsputil_init(&s->dsp, avctx);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
131 return 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
132 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
133
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
134 int ape_decode_close(APEDecoderContext *s)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
135 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
136 int i;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
137
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
138 for (i = 0; i < APE_FILTER_LEVELS; i++)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
139 free(s->filterbuf[i]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
140 if(s->data != NULL) free (s->data);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
141
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
142 return 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
143 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
144
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
145 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
146 * @defgroup rangecoder APE range decoder
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
147 * @{
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
148 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
149
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
150 #define CODE_BITS 32
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
151 #define TOP_VALUE ((unsigned int)1 << (CODE_BITS-1))
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
152 #define SHIFT_BITS (CODE_BITS - 9)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
153 #define EXTRA_BITS ((CODE_BITS-2) % 8 + 1)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
154 #define BOTTOM_VALUE (TOP_VALUE >> 8)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
155
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
156 /** Start the decoder */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
157 static inline void range_start_decoding(APEDecoderContext * ctx)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
158 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
159 /* Eugene: */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
160 #ifdef DEBUG
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
161 assert(ctx->ptr < ctx->data_end);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
162 #endif
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
163 /**/
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
164 ctx->rc.buffer = bytestream_get_byte(&ctx->ptr);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
165 ctx->rc.low = ctx->rc.buffer >> (8 - EXTRA_BITS);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
166 ctx->rc.range = (uint32_t) 1 << EXTRA_BITS;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
167 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
168
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
169 /** Perform normalization */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
170 static inline void range_dec_normalize(APEDecoderContext * ctx)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
171 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
172 while (ctx->rc.range <= BOTTOM_VALUE) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
173 #ifdef DEBUG
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
174 assert(ctx->ptr < ctx->data_end);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
175 #endif
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
176 ctx->rc.buffer = (ctx->rc.buffer << 8) | bytestream_get_byte(&ctx->ptr);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
177 ctx->rc.low = (ctx->rc.low << 8) | ((ctx->rc.buffer >> 1) & 0xFF);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
178 ctx->rc.range <<= 8;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
179 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
180 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
181
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
182 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
183 * Calculate culmulative frequency for next symbol. Does NO update!
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
184 * @param tot_f is the total frequency or (code_value)1<<shift
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
185 * @return the culmulative frequency
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
186 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
187 static inline int range_decode_culfreq(APEDecoderContext * ctx, int tot_f)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
188 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
189 range_dec_normalize(ctx);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
190 ctx->rc.help = ctx->rc.range / tot_f;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
191 return ctx->rc.low / ctx->rc.help;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
192 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
193
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
194 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
195 * Decode value with given size in bits
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
196 * @param shift number of bits to decode
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
197 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
198 static inline int range_decode_culshift(APEDecoderContext * ctx, int shift)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
199 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
200 range_dec_normalize(ctx);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
201 ctx->rc.help = ctx->rc.range >> shift;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
202 return ctx->rc.low / ctx->rc.help;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
203 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
204
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
205
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
206 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
207 * Update decoding state
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
208 * @param sy_f the interval length (frequency of the symbol)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
209 * @param lt_f the lower end (frequency sum of < symbols)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
210 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
211 static inline void range_decode_update(APEDecoderContext * ctx, int sy_f, int lt_f)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
212 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
213 ctx->rc.low -= ctx->rc.help * lt_f;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
214 ctx->rc.range = ctx->rc.help * sy_f;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
215 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
216
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
217 /** Decode n bits (n <= 16) without modelling */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
218 static inline int range_decode_bits(APEDecoderContext * ctx, int n)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
219 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
220 int sym = range_decode_culshift(ctx, n);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
221 range_decode_update(ctx, 1, sym);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
222 return sym;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
223 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
224
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
225
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
226 #define MODEL_ELEMENTS 64
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
227
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
228 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
229 * Fixed probabilities for symbols in Monkey Audio version 3.97
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
230 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
231 static const uint32_t counts_3970[65] = {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
232 0, 14824, 28224, 39348, 47855, 53994, 58171, 60926,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
233 62682, 63786, 64463, 64878, 65126, 65276, 65365, 65419,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
234 65450, 65469, 65480, 65487, 65491, 65493, 65494, 65495,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
235 65496, 65497, 65498, 65499, 65500, 65501, 65502, 65503,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
236 65504, 65505, 65506, 65507, 65508, 65509, 65510, 65511,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
237 65512, 65513, 65514, 65515, 65516, 65517, 65518, 65519,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
238 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
239 65528, 65529, 65530, 65531, 65532, 65533, 65534, 65535,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
240 65536
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
241 };
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
242
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
243 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
244 * Probability ranges for symbols in Monkey Audio version 3.97
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
245 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
246 static const uint16_t counts_diff_3970[64] = {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
247 14824, 13400, 11124, 8507, 6139, 4177, 2755, 1756,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
248 1104, 677, 415, 248, 150, 89, 54, 31,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
249 19, 11, 7, 4, 2, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
250 1, 1, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
251 1, 1, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
252 1, 1, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
253 1, 1, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
254 1, 1, 1, 1, 1, 1, 1, 1
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
255 };
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
256
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
257 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
258 * Fixed probabilities for symbols in Monkey Audio version 3.98
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
259 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
260 static const uint32_t counts_3980[65] = {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
261 0, 19578, 36160, 48417, 56323, 60899, 63265, 64435,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
262 64971, 65232, 65351, 65416, 65447, 65466, 65476, 65482,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
263 65485, 65488, 65490, 65491, 65492, 65493, 65494, 65495,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
264 65496, 65497, 65498, 65499, 65500, 65501, 65502, 65503,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
265 65504, 65505, 65506, 65507, 65508, 65509, 65510, 65511,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
266 65512, 65513, 65514, 65515, 65516, 65517, 65518, 65519,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
267 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
268 65528, 65529, 65530, 65531, 65532, 65533, 65534, 65535,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
269 65536
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
270 };
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
271
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
272 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
273 * Probability ranges for symbols in Monkey Audio version 3.98
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
274 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
275 static const uint16_t counts_diff_3980[64] = {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
276 19578, 16582, 12257, 7906, 4576, 2366, 1170, 536,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
277 261, 119, 65, 31, 19, 10, 6, 3,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
278 3, 2, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
279 1, 1, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
280 1, 1, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
281 1, 1, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
282 1, 1, 1, 1, 1, 1, 1, 1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
283 1, 1, 1, 1, 1, 1, 1, 1
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
284 };
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
285
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
286 /**
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
287 * Decode symbol
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
288 * @param counts probability range start position
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
289 * @param count_diffs probability range widths
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
290 */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
291 static inline int range_get_symbol(APEDecoderContext * ctx,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
292 const uint32_t counts[],
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
293 const uint16_t counts_diff[])
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
294 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
295 int symbol, cf;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
296
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
297 cf = range_decode_culshift(ctx, 16);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
298
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
299 /* figure out the symbol inefficiently; a binary search would be much better */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
300 for (symbol = 0; counts[symbol + 1] <= cf; symbol++);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
301
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
302 range_decode_update(ctx, counts_diff[symbol], counts[symbol]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
303
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
304 return symbol;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
305 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
306 /** @} */ // group rangecoder
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
307
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
308 static inline void update_rice(APERice *rice, int x)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
309 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
310 rice->ksum += ((x + 1) / 2) - ((rice->ksum + 16) >> 5);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
311
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
312 if (rice->k == 0)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
313 rice->k = 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
314 else if (rice->ksum < (1 << (rice->k + 4)))
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
315 rice->k--;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
316 else if (rice->ksum >= (1 << (rice->k + 5)))
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
317 rice->k++;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
318 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
319
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
320 static inline int ape_decode_value(APEDecoderContext * ctx, APERice *rice)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
321 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
322 int x, overflow;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
323
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
324 if (ctx->fileversion < 3980) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
325 int tmpk;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
326
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
327 overflow = range_get_symbol(ctx, counts_3970, counts_diff_3970);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
328
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
329 if (overflow == (MODEL_ELEMENTS - 1)) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
330 tmpk = range_decode_bits(ctx, 5);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
331 overflow = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
332 } else
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
333 tmpk = (rice->k < 1) ? 0 : rice->k - 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
334
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
335 if (tmpk <= 16)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
336 x = range_decode_bits(ctx, tmpk);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
337 else {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
338 x = range_decode_bits(ctx, 16);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
339 x |= (range_decode_bits(ctx, tmpk - 16) << 16);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
340 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
341 x += overflow << tmpk;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
342 } else {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
343 int base, pivot;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
344
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
345 pivot = rice->ksum >> 5;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
346 if (pivot == 0)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
347 pivot = 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
348
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
349 overflow = range_get_symbol(ctx, counts_3980, counts_diff_3980);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
350
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
351 if (overflow == (MODEL_ELEMENTS - 1)) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
352 overflow = range_decode_bits(ctx, 16) << 16;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
353 overflow |= range_decode_bits(ctx, 16);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
354 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
355
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
356 base = range_decode_culfreq(ctx, pivot);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
357 range_decode_update(ctx, 1, base);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
358
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
359 x = base + overflow * pivot;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
360 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
361
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
362 update_rice(rice, x);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
363
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
364 /* Convert to signed */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
365 if (x & 1)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
366 return (x >> 1) + 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
367 else
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
368 return -(x >> 1);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
369 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
370
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
371 static void entropy_decode(APEDecoderContext * ctx, int blockstodecode, int stereo)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
372 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
373 int32_t *decoded0 = ctx->decoded0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
374 int32_t *decoded1 = ctx->decoded1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
375
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
376 ctx->blocksdecoded = blockstodecode;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
377
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
378 if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
379 /* We are pure silence, just memset the output buffer. */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
380 memset(decoded0, 0, blockstodecode * sizeof(int32_t));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
381 memset(decoded1, 0, blockstodecode * sizeof(int32_t));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
382 } else {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
383 while (blockstodecode--) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
384 *decoded0++ = ape_decode_value(ctx, &ctx->riceY);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
385 if (stereo)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
386 *decoded1++ = ape_decode_value(ctx, &ctx->riceX);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
387 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
388 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
389
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
390 if (ctx->blocksdecoded == ctx->currentframeblocks)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
391 range_dec_normalize(ctx); /* normalize to use up all bytes */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
392 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
393
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
394 static void init_entropy_decoder(APEDecoderContext * ctx)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
395 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
396 /* Read the CRC */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
397 ctx->CRC = bytestream_get_be32(&ctx->ptr);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
398
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
399 /* Read the frame flags if they exist */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
400 ctx->frameflags = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
401 if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000)) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
402 ctx->CRC &= ~0x80000000;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
403
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
404 ctx->frameflags = bytestream_get_be32(&ctx->ptr);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
405 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
406
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
407 /* Keep a count of the blocks decoded in this frame */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
408 ctx->blocksdecoded = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
409
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
410 /* Initialise the rice structs */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
411 ctx->riceX.k = 10;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
412 ctx->riceX.ksum = (1 << ctx->riceX.k) * 16;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
413 ctx->riceY.k = 10;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
414 ctx->riceY.ksum = (1 << ctx->riceY.k) * 16;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
415
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
416 /* The first 8 bits of input are ignored. */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
417 ctx->ptr++;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
418
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
419 range_start_decoding(ctx);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
420 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
421
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
422 static const int32_t initial_coeffs[4] = {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
423 360, 317, -109, 98
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
424 };
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
425
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
426 static void init_predictor_decoder(APEDecoderContext * ctx)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
427 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
428 APEPredictor *p = &ctx->predictor;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
429
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
430 /* Zero the history buffers */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
431 memset(p->historybuffer, 0, PREDICTOR_SIZE * sizeof(int32_t));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
432 p->buf = p->historybuffer;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
433
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
434 /* Initialise and zero the co-efficients */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
435 memcpy(p->coeffsA[0], initial_coeffs, sizeof(initial_coeffs));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
436 memcpy(p->coeffsA[1], initial_coeffs, sizeof(initial_coeffs));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
437 memset(p->coeffsB, 0, sizeof(p->coeffsB));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
438
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
439 p->filterA[0] = p->filterA[1] = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
440 p->filterB[0] = p->filterB[1] = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
441 p->lastA[0] = p->lastA[1] = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
442 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
443
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
444 /** Get inverse sign of integer (-1 for positive, 1 for negative and 0 for zero) */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
445 static inline int APESIGN(int32_t x) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
446 return (x < 0) - (x > 0);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
447 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
448
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
449 static int predictor_update_filter(APEPredictor *p, const int decoded, const int filter, const int delayA, const int delayB, const int adaptA, const int adaptB)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
450 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
451 int32_t predictionA, predictionB;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
452
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
453 p->buf[delayA] = p->lastA[filter];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
454 p->buf[adaptA] = APESIGN(p->buf[delayA]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
455 p->buf[delayA - 1] = p->buf[delayA] - p->buf[delayA - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
456 p->buf[adaptA - 1] = APESIGN(p->buf[delayA - 1]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
457
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
458 predictionA = p->buf[delayA ] * p->coeffsA[filter][0] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
459 p->buf[delayA - 1] * p->coeffsA[filter][1] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
460 p->buf[delayA - 2] * p->coeffsA[filter][2] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
461 p->buf[delayA - 3] * p->coeffsA[filter][3];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
462
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
463 /* Apply a scaled first-order filter compression */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
464 p->buf[delayB] = p->filterA[filter ^ 1] - ((p->filterB[filter] * 31) >> 5);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
465 p->buf[adaptB] = APESIGN(p->buf[delayB]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
466 p->buf[delayB - 1] = p->buf[delayB] - p->buf[delayB - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
467 p->buf[adaptB - 1] = APESIGN(p->buf[delayB - 1]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
468 p->filterB[filter] = p->filterA[filter ^ 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
469
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
470 predictionB = p->buf[delayB ] * p->coeffsB[filter][0] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
471 p->buf[delayB - 1] * p->coeffsB[filter][1] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
472 p->buf[delayB - 2] * p->coeffsB[filter][2] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
473 p->buf[delayB - 3] * p->coeffsB[filter][3] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
474 p->buf[delayB - 4] * p->coeffsB[filter][4];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
475
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
476 p->lastA[filter] = decoded + ((predictionA + (predictionB >> 1)) >> 10);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
477 p->filterA[filter] = p->lastA[filter] + ((p->filterA[filter] * 31) >> 5);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
478
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
479 if (!decoded) // no need updating filter coefficients
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
480 return p->filterA[filter];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
481
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
482 if (decoded > 0) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
483 p->coeffsA[filter][0] -= p->buf[adaptA ];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
484 p->coeffsA[filter][1] -= p->buf[adaptA - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
485 p->coeffsA[filter][2] -= p->buf[adaptA - 2];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
486 p->coeffsA[filter][3] -= p->buf[adaptA - 3];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
487
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
488 p->coeffsB[filter][0] -= p->buf[adaptB ];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
489 p->coeffsB[filter][1] -= p->buf[adaptB - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
490 p->coeffsB[filter][2] -= p->buf[adaptB - 2];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
491 p->coeffsB[filter][3] -= p->buf[adaptB - 3];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
492 p->coeffsB[filter][4] -= p->buf[adaptB - 4];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
493 } else {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
494 p->coeffsA[filter][0] += p->buf[adaptA ];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
495 p->coeffsA[filter][1] += p->buf[adaptA - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
496 p->coeffsA[filter][2] += p->buf[adaptA - 2];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
497 p->coeffsA[filter][3] += p->buf[adaptA - 3];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
498
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
499 p->coeffsB[filter][0] += p->buf[adaptB ];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
500 p->coeffsB[filter][1] += p->buf[adaptB - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
501 p->coeffsB[filter][2] += p->buf[adaptB - 2];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
502 p->coeffsB[filter][3] += p->buf[adaptB - 3];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
503 p->coeffsB[filter][4] += p->buf[adaptB - 4];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
504 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
505 return p->filterA[filter];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
506 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
507
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
508 static void predictor_decode_stereo(APEDecoderContext * ctx, int count)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
509 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
510 int32_t predictionA, predictionB;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
511 APEPredictor *p = &ctx->predictor;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
512 int32_t *decoded0 = ctx->decoded0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
513 int32_t *decoded1 = ctx->decoded1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
514
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
515 while (count--) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
516 /* Predictor Y */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
517 predictionA = predictor_update_filter(p, *decoded0, 0, YDELAYA, YDELAYB, YADAPTCOEFFSA, YADAPTCOEFFSB);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
518 predictionB = predictor_update_filter(p, *decoded1, 1, XDELAYA, XDELAYB, XADAPTCOEFFSA, XADAPTCOEFFSB);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
519 *(decoded0++) = predictionA;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
520 *(decoded1++) = predictionB;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
521
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
522 /* Combined */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
523 p->buf++;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
524
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
525 /* Have we filled the history buffer? */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
526 if (p->buf == p->historybuffer + HISTORY_SIZE) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
527 memmove(p->historybuffer, p->buf, PREDICTOR_SIZE * sizeof(int32_t));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
528 p->buf = p->historybuffer;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
529 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
530 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
531 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
532
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
533 static void predictor_decode_mono(APEDecoderContext * ctx, int count)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
534 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
535 APEPredictor *p = &ctx->predictor;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
536 int32_t *decoded0 = ctx->decoded0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
537 int32_t predictionA, currentA, A;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
538
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
539 currentA = p->lastA[0];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
540
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
541 while (count--) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
542 A = *decoded0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
543
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
544 p->buf[YDELAYA] = currentA;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
545 p->buf[YDELAYA - 1] = p->buf[YDELAYA] - p->buf[YDELAYA - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
546
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
547 predictionA = p->buf[YDELAYA ] * p->coeffsA[0][0] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
548 p->buf[YDELAYA - 1] * p->coeffsA[0][1] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
549 p->buf[YDELAYA - 2] * p->coeffsA[0][2] +
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
550 p->buf[YDELAYA - 3] * p->coeffsA[0][3];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
551
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
552 currentA = A + (predictionA >> 10);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
553
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
554 p->buf[YADAPTCOEFFSA] = APESIGN(p->buf[YDELAYA ]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
555 p->buf[YADAPTCOEFFSA - 1] = APESIGN(p->buf[YDELAYA - 1]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
556
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
557 if (A > 0) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
558 p->coeffsA[0][0] -= p->buf[YADAPTCOEFFSA ];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
559 p->coeffsA[0][1] -= p->buf[YADAPTCOEFFSA - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
560 p->coeffsA[0][2] -= p->buf[YADAPTCOEFFSA - 2];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
561 p->coeffsA[0][3] -= p->buf[YADAPTCOEFFSA - 3];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
562 } else if (A < 0) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
563 p->coeffsA[0][0] += p->buf[YADAPTCOEFFSA ];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
564 p->coeffsA[0][1] += p->buf[YADAPTCOEFFSA - 1];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
565 p->coeffsA[0][2] += p->buf[YADAPTCOEFFSA - 2];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
566 p->coeffsA[0][3] += p->buf[YADAPTCOEFFSA - 3];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
567 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
568
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
569 p->buf++;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
570
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
571 /* Have we filled the history buffer? */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
572 if (p->buf == p->historybuffer + HISTORY_SIZE) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
573 memmove(p->historybuffer, p->buf, PREDICTOR_SIZE * sizeof(int32_t));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
574 p->buf = p->historybuffer;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
575 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
576
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
577 p->filterA[0] = currentA + ((p->filterA[0] * 31) >> 5);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
578 *(decoded0++) = p->filterA[0];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
579 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
580
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
581 p->lastA[0] = currentA;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
582 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
583
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
584 static void do_init_filter(APEFilter *f, int16_t * buf, int order)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
585 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
586 f->coeffs = buf;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
587 f->historybuffer = buf + order;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
588 f->delay = f->historybuffer + order * 2;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
589 f->adaptcoeffs = f->historybuffer + order;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
590
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
591 memset(f->historybuffer, 0, (order * 2) * sizeof(int16_t));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
592 memset(f->coeffs, 0, order * sizeof(int16_t));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
593 f->avg = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
594 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
595
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
596 static void init_filter(APEDecoderContext * ctx, APEFilter *f, int16_t * buf, int order)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
597 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
598 do_init_filter(&f[0], buf, order);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
599 do_init_filter(&f[1], buf + order * 3 + HISTORY_SIZE, order);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
600 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
601
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
602 static inline void do_apply_filter(int version, APEFilter *f, int32_t *data, int count, int order, int fracbits)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
603 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
604 int res;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
605 int absres;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
606
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
607 while (count--) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
608 /* round fixedpoint scalar product */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
609 res = (scalarproduct(f->delay - order, f->coeffs, order) + (1 << (fracbits - 1))) >> fracbits;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
610
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
611 if (*data < 0)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
612 vector_add(f->coeffs, f->adaptcoeffs - order, order);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
613 else if (*data > 0)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
614 vector_sub(f->coeffs, f->adaptcoeffs - order, order);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
615
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
616 res += *data;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
617
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
618 *data++ = res;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
619
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
620 /* Update the output history */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
621 *f->delay++ = av_clip_int16(res);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
622
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
623 if (version < 3980) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
624 /* Version ??? to < 3.98 files (untested) */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
625 f->adaptcoeffs[0] = (res == 0) ? 0 : ((res >> 28) & 8) - 4;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
626 f->adaptcoeffs[-4] >>= 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
627 f->adaptcoeffs[-8] >>= 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
628 } else {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
629 /* Version 3.98 and later files */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
630
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
631 /* Update the adaption coefficients */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
632 absres = (res < 0 ? -res : res);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
633
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
634 if (absres > (f->avg * 3))
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
635 *f->adaptcoeffs = ((res >> 25) & 64) - 32;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
636 else if (absres > (f->avg * 4) / 3)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
637 *f->adaptcoeffs = ((res >> 26) & 32) - 16;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
638 else if (absres > 0)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
639 *f->adaptcoeffs = ((res >> 27) & 16) - 8;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
640 else
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
641 *f->adaptcoeffs = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
642
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
643 f->avg += (absres - f->avg) / 16;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
644
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
645 f->adaptcoeffs[-1] >>= 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
646 f->adaptcoeffs[-2] >>= 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
647 f->adaptcoeffs[-8] >>= 1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
648 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
649
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
650 f->adaptcoeffs++;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
651
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
652 /* Have we filled the history buffer? */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
653 if (f->delay == f->historybuffer + HISTORY_SIZE + (order * 2)) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
654 memmove(f->historybuffer, f->delay - (order * 2),
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
655 (order * 2) * sizeof(int16_t));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
656 f->delay = f->historybuffer + order * 2;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
657 f->adaptcoeffs = f->historybuffer + order;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
658 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
659 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
660 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
661
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
662 static void apply_filter(APEDecoderContext * ctx, APEFilter *f,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
663 int32_t * data0, int32_t * data1,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
664 int count, int order, int fracbits)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
665 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
666 do_apply_filter(ctx->fileversion, &f[0], data0, count, order, fracbits);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
667 if (data1)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
668 do_apply_filter(ctx->fileversion, &f[1], data1, count, order, fracbits);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
669 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
670
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
671 static void ape_apply_filters(APEDecoderContext * ctx, int32_t * decoded0,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
672 int32_t * decoded1, int count)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
673 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
674 int i;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
675
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
676 for (i = 0; i < APE_FILTER_LEVELS; i++) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
677 if (!ape_filter_orders[ctx->fset][i])
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
678 break;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
679 apply_filter(ctx, ctx->filters[i], decoded0, decoded1, count, ape_filter_orders[ctx->fset][i], ape_filter_fracbits[ctx->fset][i]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
680 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
681 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
682
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
683 static void init_frame_decoder(APEDecoderContext * ctx)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
684 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
685 int i;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
686 init_entropy_decoder(ctx);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
687 init_predictor_decoder(ctx);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
688
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
689 for (i = 0; i < APE_FILTER_LEVELS; i++) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
690 if (!ape_filter_orders[ctx->fset][i])
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
691 break;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
692 init_filter(ctx, ctx->filters[i], ctx->filterbuf[i], ape_filter_orders[ctx->fset][i]);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
693 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
694 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
695
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
696 static void ape_unpack_mono(APEDecoderContext * ctx, int count)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
697 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
698 int32_t left;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
699 int32_t *decoded0 = ctx->decoded0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
700 int32_t *decoded1 = ctx->decoded1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
701
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
702 if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
703 entropy_decode(ctx, count, 0);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
704 /* We are pure silence, so we're done. */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
705 av_log(ctx->avctx, AV_LOG_DEBUG, "pure silence mono\n");
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
706 return;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
707 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
708
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
709 entropy_decode(ctx, count, 0);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
710 ape_apply_filters(ctx, decoded0, NULL, count);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
711
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
712 /* Now apply the predictor decoding */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
713 predictor_decode_mono(ctx, count);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
714
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
715 /* Pseudo-stereo - just copy left channel to right channel */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
716 if (ctx->channels == 2) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
717 while (count--) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
718 left = *decoded0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
719 *(decoded1++) = *(decoded0++) = left;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
720 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
721 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
722 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
723
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
724 static void ape_unpack_stereo(APEDecoderContext * ctx, int count)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
725 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
726 int32_t left, right;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
727 int32_t *decoded0 = ctx->decoded0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
728 int32_t *decoded1 = ctx->decoded1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
729
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
730 if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
731 /* We are pure silence, so we're done. */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
732 av_log(ctx->avctx, AV_LOG_DEBUG, "pure silence stereo\n");
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
733 return;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
734 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
735
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
736 entropy_decode(ctx, count, 1);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
737 ape_apply_filters(ctx, decoded0, decoded1, count);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
738
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
739 /* Now apply the predictor decoding */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
740 predictor_decode_stereo(ctx, count);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
741
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
742 /* Decorrelate and scale to output depth */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
743 while (count--) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
744 left = *decoded1 - (*decoded0 / 2);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
745 right = left + *decoded0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
746
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
747 *(decoded0++) = left;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
748 *(decoded1++) = right;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
749 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
750 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
751
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
752 int ape_decode_frame(APEDecoderContext *s,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
753 void *data, int *data_size,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
754 uint8_t * buf, int buf_size)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
755 {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
756 int16_t *samples = data;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
757 int nblocks;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
758 int i, n;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
759 int blockstodecode;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
760 int bytes_used;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
761 int aligned_size;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
762
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
763 if (buf_size == 0 && !s->samples) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
764 *data_size = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
765 return 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
766 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
767
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
768 /* should not happen but who knows */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
769 if (BLOCKS_PER_LOOP * 2 * s->channels > *data_size) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
770 av_log (avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc! (max is %d where you have %d)\n", *data_size, s->samples * 2 * s->channels);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
771 return -1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
772 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
773
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
774 if(!s->samples){
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
775 #ifdef DEBUG
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
776 //fprintf(stderr, "apedec.c: ape_decode_frame(): initializing frame decoder\n");
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
777 #endif
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
778 //s->data = realloc(s->data, (buf_size + 3) & ~3);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
779 aligned_size = (s->max_packet_size + 3) & ~3;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
780 if(s->data == NULL) s->data = malloc(aligned_size);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
781 bswap_buf((uint32_t*)s->data, (uint32_t*)buf, aligned_size >> 2);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
782 s->ptr = s->last_ptr = s->data;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
783 //s->data_end = s->data + buf_size;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
784 s->data_end = s->data + aligned_size; // ??? it works ... Eugene
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
785
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
786 nblocks = s->samples = bytestream_get_be32(&s->ptr);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
787 n = bytestream_get_be32(&s->ptr);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
788 if(n < 0 || n > 3){
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
789 av_log(avctx, AV_LOG_ERROR, "Incorrect offset passed, %d\n", n);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
790 s->data = NULL;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
791 return -1;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
792 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
793 s->ptr += n;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
794
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
795 s->currentframeblocks = nblocks;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
796 buf += 4;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
797 if (s->samples <= 0) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
798 *data_size = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
799 return buf_size;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
800 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
801
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
802 memset(s->decoded0, 0, sizeof(s->decoded0));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
803 memset(s->decoded1, 0, sizeof(s->decoded1));
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
804
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
805 /* Initialize the frame decoder */
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
806 init_frame_decoder(s);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
807 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
808
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
809 if (!s->data) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
810 *data_size = 0;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
811 return buf_size;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
812 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
813 #ifdef DEBUG
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
814 //fprintf(stderr, "apedec.c: ape_decode_frame(): decoding frame's part\n");
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
815 #endif
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
816
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
817 nblocks = s->samples;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
818 blockstodecode = FFMIN(BLOCKS_PER_LOOP, nblocks);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
819
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
820 if ((s->channels == 1) || (s->frameflags & APE_FRAMECODE_PSEUDO_STEREO))
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
821 ape_unpack_mono(s, blockstodecode);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
822 else
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
823 ape_unpack_stereo(s, blockstodecode);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
824
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
825 for (i = 0; i < blockstodecode; i++) {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
826 *samples++ = s->decoded0[i];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
827 if(s->channels == 2)
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
828 *samples++ = s->decoded1[i];
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
829 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
830
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
831 s->samples -= blockstodecode;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
832 #ifdef DEBUG
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
833 //fprintf(stderr, "apedec.c: ape_decode_frame(): samples left: %d, total bytes left: %d\n", s->samples, s->data_end - s->ptr);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
834 assert(s->ptr < s->data_end);
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
835 #endif
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
836
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
837 *data_size = blockstodecode * 2 * s->channels;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
838 bytes_used = s->samples ? s->ptr - s->last_ptr : buf_size;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
839 s->last_ptr = s->ptr;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
840 return bytes_used;
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
841 }
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
842
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
843 /*AVCodec ape_decoder = {
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
844 "ape",
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
845 CODEC_TYPE_AUDIO,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
846 CODEC_ID_APE,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
847 sizeof(APEDecoderContext),
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
848 ape_decode_init,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
849 NULL,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
850 ape_decode_close,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
851 ape_decode_frame,
cc5e9ec110a4 Added initial version of Monkey's Audio plugin
Eugene Zagidullin <e.asphyx@gmail.com>
parents:
diff changeset
852 };*/