Mercurial > audlegacy-plugins
annotate src/tta/ttadec.c @ 3195:16d4308fb36e
alsa-ng: Set type hint on prefs window, and don't use deprecated GTK funcs.
author | John Lindgren <john.lindgren@tds.net> |
---|---|
date | Thu, 09 Jul 2009 11:03:32 -0400 |
parents | f1b6f1b2cdb3 |
children |
rev | line source |
---|---|
290 | 1 /* |
2 * ttadec.c | |
3 * | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
4 * Description: TTAv1 decoder library |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
5 * Developed by: Alexander Djourik <ald@true-audio.com> |
290 | 6 * |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
7 * Copyright (c) 1999-2007 Alexander Djourik. All rights reserved. |
290 | 8 * |
9 */ | |
10 | |
11 /* | |
12 * This library is free software; you can redistribute it and/or | |
13 * modify it under the terms of the GNU Lesser General Public | |
14 * License as published by the Free Software Foundation; either | |
15 * version 2.1 of the License, or (at your option) any later version. | |
16 * | |
17 * This library is distributed in the hope that it will be useful, | |
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 * Lesser General Public License for more details. | |
21 * | |
22 * You should have received a copy of the GNU Lesser General Public | |
23 * License along with this library; if not, write to the Free Software | |
2835 | 24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
290 | 25 * |
26 * Please see the file COPYING in this directory for full copyright | |
27 * information. | |
28 */ | |
29 | |
30 #include <stdlib.h> | |
31 #include <stdio.h> | |
32 #include <string.h> | |
33 | |
912
5bd17596c7e9
[svn] - patches from upstream TTA author. see http://boards.nenolod.net/viewtopic.php?t=375
nenolod
parents:
551
diff
changeset
|
34 #include "ttadec.h" |
290 | 35 #include "ttalib.h" |
36 | |
37 /******************* static variables and structures *******************/ | |
38 | |
39 static unsigned char isobuffers[ISO_BUFFERS_SIZE + 4]; | |
40 static unsigned char *iso_buffers_end = isobuffers + ISO_BUFFERS_SIZE; | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
41 static unsigned int pcm_buffer_size; |
290 | 42 |
43 static decoder tta[MAX_NCH]; // decoder state | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
44 static int cache[MAX_NCH]; // decoder cache |
290 | 45 |
46 tta_info *ttainfo; // currently playing file info | |
47 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
48 static unsigned int fframes; // number of frames in file |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
49 static unsigned int framelen; // the frame length in samples |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
50 static unsigned int lastlen; // the length of the last frame in samples |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
51 static unsigned int data_pos; // currently playing frame index |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
52 static unsigned int data_cur; // the playing position in frame |
290 | 53 |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
54 static int maxvalue; // output data max value |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
55 static unsigned int *seek_table; // the playing position table |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
56 static unsigned int st_state; //seek table status |
290 | 57 |
912
5bd17596c7e9
[svn] - patches from upstream TTA author. see http://boards.nenolod.net/viewtopic.php?t=375
nenolod
parents:
551
diff
changeset
|
58 static __uint32_t frame_crc32; |
5bd17596c7e9
[svn] - patches from upstream TTA author. see http://boards.nenolod.net/viewtopic.php?t=375
nenolod
parents:
551
diff
changeset
|
59 static __uint32_t bit_count; |
5bd17596c7e9
[svn] - patches from upstream TTA author. see http://boards.nenolod.net/viewtopic.php?t=375
nenolod
parents:
551
diff
changeset
|
60 static __uint32_t bit_cache; |
290 | 61 static unsigned char *bitpos; |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
62 static unsigned int bitrate; |
290 | 63 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
64 /************************* crc32 functions *****************************/ |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
65 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
66 #define UPDATE_CRC32(x, crc) crc = \ |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
67 (((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc^x) & 0xFF]) |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
68 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
69 static __uint32_t |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
70 crc32 (unsigned char *buffer, unsigned int len) { |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
71 unsigned int i; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
72 unsigned int crc = 0xFFFFFFFF; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
73 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
74 for (i = 0; i < len; i++) UPDATE_CRC32(buffer[i], crc); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
75 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
76 return (crc ^ 0xFFFFFFFF); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
77 } |
290 | 78 |
79 /************************* bit operations ******************************/ | |
80 | |
81 static void init_buffer_read() { | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
82 frame_crc32 = 0xFFFFFFFFUL; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
83 bit_count = bit_cache = 0; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
84 bitpos = iso_buffers_end; |
290 | 85 } |
86 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
87 __inline void get_binary(unsigned int *value, unsigned int bits) { |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
88 while (bit_count < bits) { |
290 | 89 if (bitpos == iso_buffers_end) { |
1978 | 90 int res = aud_vfs_fread(isobuffers, 1, |
290 | 91 ISO_BUFFERS_SIZE, ttainfo->HANDLE); |
92 if (!res) { | |
93 ttainfo->STATE = READ_ERROR; | |
94 return; | |
95 } | |
96 bitpos = isobuffers; | |
97 } | |
98 | |
99 UPDATE_CRC32(*bitpos, frame_crc32); | |
100 bit_cache |= *bitpos << bit_count; | |
101 bit_count += 8; | |
102 bitpos++; | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
103 } |
290 | 104 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
105 *value = bit_cache & bit_mask[bits]; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
106 bit_cache >>= bits; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
107 bit_count -= bits; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
108 bit_cache &= bit_mask[bit_count]; |
290 | 109 } |
110 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
111 __inline void get_unary(unsigned int *value) { |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
112 *value = 0; |
290 | 113 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
114 while (!(bit_cache ^ bit_mask[bit_count])) { |
290 | 115 if (bitpos == iso_buffers_end) { |
1978 | 116 int res = aud_vfs_fread(isobuffers, 1, |
290 | 117 ISO_BUFFERS_SIZE, ttainfo->HANDLE); |
118 if (!res) { | |
119 ttainfo->STATE = READ_ERROR; | |
120 return; | |
121 } | |
122 bitpos = isobuffers; | |
123 } | |
124 | |
125 *value += bit_count; | |
126 bit_cache = *bitpos++; | |
127 UPDATE_CRC32(bit_cache, frame_crc32); | |
128 bit_count = 8; | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
129 } |
290 | 130 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
131 while (bit_cache & 1) { |
290 | 132 (*value)++; |
133 bit_cache >>= 1; | |
134 bit_count--; | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
135 } |
290 | 136 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
137 bit_cache >>= 1; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
138 bit_count--; |
290 | 139 } |
140 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
141 static int done_buffer_read() { |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
142 unsigned int crc32, rbytes, res; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
143 frame_crc32 ^= 0xFFFFFFFFUL; |
290 | 144 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
145 rbytes = iso_buffers_end - bitpos; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
146 if (rbytes < sizeof(int)) { |
290 | 147 memcpy(isobuffers, bitpos, 4); |
1978 | 148 res = aud_vfs_fread(isobuffers + rbytes, 1, |
290 | 149 ISO_BUFFERS_SIZE - rbytes, ttainfo->HANDLE); |
150 if (!res) { | |
151 ttainfo->STATE = READ_ERROR; | |
152 return 0; | |
153 } | |
154 bitpos = isobuffers; | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
155 } |
290 | 156 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
157 memcpy(&crc32, bitpos, 4); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
158 crc32 = ENDSWAP_INT32(crc32); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
159 bitpos += sizeof(int); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
160 res = (crc32 != frame_crc32); |
290 | 161 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
162 bit_cache = bit_count = 0; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
163 frame_crc32 = 0xFFFFFFFFUL; |
290 | 164 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
165 // calculate dynamic bitrate |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
166 if (data_pos < fframes) { |
290 | 167 rbytes = seek_table[data_pos] - |
168 seek_table[data_pos - 1]; | |
169 bitrate = (rbytes << 3) / 1070; | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
170 } |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
171 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
172 return res; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
173 } |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
174 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
175 /************************** filter functions ****************************/ |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
176 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
177 ///////// Filter Settings ////////// |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
178 static int flt_set[3] = {10, 9, 10}; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
179 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
180 __inline void |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
181 memshl (register int *pA, register int *pB) { |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
182 *pA++ = *pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
183 *pA++ = *pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
184 *pA++ = *pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
185 *pA++ = *pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
186 *pA++ = *pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
187 *pA++ = *pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
188 *pA++ = *pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
189 *pA = *pB; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
190 } |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
191 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
192 __inline void |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
193 hybrid_filter (fltst *fs, int *in) { |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
194 register int *pA = fs->dl; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
195 register int *pB = fs->qm; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
196 register int *pM = fs->dx; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
197 register int sum = fs->round; |
290 | 198 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
199 if (!fs->error) { |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
200 sum += *pA++ * *pB, pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
201 sum += *pA++ * *pB, pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
202 sum += *pA++ * *pB, pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
203 sum += *pA++ * *pB, pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
204 sum += *pA++ * *pB, pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
205 sum += *pA++ * *pB, pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
206 sum += *pA++ * *pB, pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
207 sum += *pA++ * *pB, pB++; pM += 8; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
208 } else if (fs->error < 0) { |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
209 sum += *pA++ * (*pB -= *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
210 sum += *pA++ * (*pB -= *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
211 sum += *pA++ * (*pB -= *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
212 sum += *pA++ * (*pB -= *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
213 sum += *pA++ * (*pB -= *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
214 sum += *pA++ * (*pB -= *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
215 sum += *pA++ * (*pB -= *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
216 sum += *pA++ * (*pB -= *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
217 } else { |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
218 sum += *pA++ * (*pB += *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
219 sum += *pA++ * (*pB += *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
220 sum += *pA++ * (*pB += *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
221 sum += *pA++ * (*pB += *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
222 sum += *pA++ * (*pB += *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
223 sum += *pA++ * (*pB += *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
224 sum += *pA++ * (*pB += *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
225 sum += *pA++ * (*pB += *pM++), pB++; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
226 } |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
227 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
228 *(pM-0) = ((*(pA-1) >> 30) | 1) << 2; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
229 *(pM-1) = ((*(pA-2) >> 30) | 1) << 1; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
230 *(pM-2) = ((*(pA-3) >> 30) | 1) << 1; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
231 *(pM-3) = ((*(pA-4) >> 30) | 1); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
232 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
233 fs->error = *in; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
234 *in += (sum >> fs->shift); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
235 *pA = *in; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
236 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
237 *(pA-1) = *(pA-0) - *(pA-1); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
238 *(pA-2) = *(pA-1) - *(pA-2); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
239 *(pA-3) = *(pA-2) - *(pA-3); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
240 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
241 memshl (fs->dl, fs->dl + 1); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
242 memshl (fs->dx, fs->dx + 1); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
243 } |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
244 |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
245 void |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
246 filter_init (fltst *fs, int shift) { |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
247 memset (fs, 0, sizeof(fltst)); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
248 fs->shift = shift; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
249 fs->round = 1 << (shift - 1); |
290 | 250 } |
251 | |
252 /************************* decoder functions ****************************/ | |
253 | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
254 int id3v2_header_length (tta_info *ttainfo) { |
290 | 255 struct { |
256 unsigned char id[3]; | |
257 unsigned short version; | |
258 unsigned char flags; | |
259 unsigned char size[4]; | |
260 } __ATTRIBUTE_PACKED__ id3v2; | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
261 unsigned int len = 0; |
290 | 262 |
1978 | 263 if (!aud_vfs_fread(&id3v2, sizeof(id3v2), 1, ttainfo->HANDLE) || |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
264 memcmp(id3v2.id, "ID3", 3) || |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
265 id3v2.size[0] & 0x80) |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
266 { |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
267 fseek (ttainfo->HANDLE, 0, SEEK_SET); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
268 return 0; |
290 | 269 } |
270 | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
271 len = (id3v2.size[0] & 0x7f); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
272 len = (len << 7) | (id3v2.size[1] & 0x7f); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
273 len = (len << 7) | (id3v2.size[2] & 0x7f); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
274 len = (len << 7) | (id3v2.size[3] & 0x7f); |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
275 len += 10; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
276 if (id3v2.flags & (1 << 4)) len += 10; |
290 | 277 |
278 return len; | |
279 } | |
280 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
281 int open_tta_file (const char *filename, tta_info *info, unsigned int data_offset) { |
1237
0d5b0f861bf0
- quick fix for link breakage to libaudid3tag.so when --prefix is specified.
Yoshiki Yazawa <yaz@cc.rim.or.jp>
parents:
1190
diff
changeset
|
282 VFSFile *infile; |
290 | 283 tta_hdr ttahdr; |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
284 unsigned int checksum; |
290 | 285 |
286 // clear the memory | |
287 memset (info, 0, sizeof(tta_info)); | |
288 | |
1978 | 289 info->HANDLE = infile = aud_vfs_fopen(filename, "rb"); |
290 | 290 if (!infile) return OPEN_ERROR; |
291 | |
292 // read id3v2 header | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
293 // if (!data_offset) |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
294 // data_offset = id3v2_header_length(info); |
290 | 295 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
296 data_offset = get_id3_tags (filename, info); |
1978 | 297 aud_vfs_fseek (infile, data_offset, SEEK_SET); |
290 | 298 |
299 // read TTA header | |
1978 | 300 if (aud_vfs_fread (&ttahdr, 1, sizeof (ttahdr), infile) == 0) { |
301 aud_vfs_fclose (infile); | |
290 | 302 info->STATE = READ_ERROR; |
303 return -1; | |
304 } | |
305 | |
306 // check for TTA3 signature | |
307 if (ENDSWAP_INT32(ttahdr.TTAid) != TTA1_SIGN) { | |
1978 | 308 aud_vfs_fclose (infile); |
290 | 309 info->STATE = FORMAT_ERROR; |
310 return -1; | |
311 } | |
312 | |
313 ttahdr.CRC32 = ENDSWAP_INT32(ttahdr.CRC32); | |
314 checksum = crc32((unsigned char *) &ttahdr, | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
315 sizeof(tta_hdr) - sizeof(int)); |
290 | 316 if (checksum != ttahdr.CRC32) { |
1978 | 317 aud_vfs_fclose (infile); |
290 | 318 info->STATE = FILE_ERROR; |
319 return -1; | |
320 } | |
321 | |
322 ttahdr.AudioFormat = ENDSWAP_INT16(ttahdr.AudioFormat); | |
323 ttahdr.NumChannels = ENDSWAP_INT16(ttahdr.NumChannels); | |
324 ttahdr.BitsPerSample = ENDSWAP_INT16(ttahdr.BitsPerSample); | |
325 ttahdr.SampleRate = ENDSWAP_INT32(ttahdr.SampleRate); | |
326 ttahdr.DataLength = ENDSWAP_INT32(ttahdr.DataLength); | |
327 | |
328 // check for player supported formats | |
329 if (ttahdr.AudioFormat != WAVE_FORMAT_PCM || | |
330 ttahdr.NumChannels > MAX_NCH || | |
331 ttahdr.BitsPerSample > MAX_BPS ||( | |
332 ttahdr.SampleRate != 16000 && | |
333 ttahdr.SampleRate != 22050 && | |
334 ttahdr.SampleRate != 24000 && | |
335 ttahdr.SampleRate != 32000 && | |
336 ttahdr.SampleRate != 44100 && | |
337 ttahdr.SampleRate != 48000 && | |
338 ttahdr.SampleRate != 64000 && | |
339 ttahdr.SampleRate != 88200 && | |
340 ttahdr.SampleRate != 96000)) { | |
1978 | 341 aud_vfs_fclose (infile); |
290 | 342 info->STATE = FORMAT_ERROR; |
343 return FORMAT_ERROR; | |
344 } | |
345 | |
346 // fill the File Info | |
347 info->HANDLE = infile; | |
348 info->NCH = ttahdr.NumChannels; | |
349 info->BPS = ttahdr.BitsPerSample; | |
350 info->BSIZE = (ttahdr.BitsPerSample + 7)/8; | |
351 info->FORMAT = ttahdr.AudioFormat; | |
352 info->SAMPLERATE = ttahdr.SampleRate; | |
353 info->DATALENGTH = ttahdr.DataLength; | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
354 info->FRAMELEN = (int) (FRAME_TIME * ttahdr.SampleRate); |
290 | 355 info->LENGTH = ttahdr.DataLength / ttahdr.SampleRate; |
356 info->DATAPOS = data_offset; | |
357 | |
358 | |
359 return 0; | |
360 } | |
361 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
362 static void rice_init(adapt *rice, unsigned int k0, unsigned int k1) { |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
363 rice->k0 = k0; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
364 rice->k1 = k1; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
365 rice->sum0 = shift_16[k0]; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
366 rice->sum1 = shift_16[k1]; |
290 | 367 } |
368 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
369 static void decoder_init(decoder *tta, int nch, int byte_size) { |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
370 int shift = flt_set[byte_size - 1]; |
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
371 int i; |
290 | 372 |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
373 for (i = 0; i < nch; i++) { |
290 | 374 filter_init(&tta[i].fst, shift); |
375 rice_init(&tta[i].rice, 10, 10); | |
376 tta[i].last = 0; | |
1012
d0d99b22e393
[svn] import major update by Aleksander Djuric (the original author).
yaz
parents:
912
diff
changeset
|
377 } |
290 | 378 } |
379 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
380 static void seek_table_init (unsigned int *seek_table, |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
381 unsigned int len, unsigned int data_offset) { |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
382 unsigned int *st, frame_len; |
290 | 383 |
384 for (st = seek_table; st < (seek_table + len); st++) { | |
385 frame_len = ENDSWAP_INT32(*st); | |
386 *st = data_offset; | |
387 data_offset += frame_len; | |
388 } | |
389 } | |
390 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
391 int set_position (unsigned int pos) { |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
392 unsigned int seek_pos; |
290 | 393 |
394 if (pos >= fframes) return 0; | |
395 if (!st_state) { | |
396 ttainfo->STATE = FILE_ERROR; | |
397 return -1; | |
398 } | |
399 | |
400 seek_pos = ttainfo->DATAPOS + seek_table[data_pos = pos]; | |
1978 | 401 aud_vfs_fseek(ttainfo->HANDLE, seek_pos, SEEK_SET); |
290 | 402 |
403 data_cur = 0; | |
404 framelen = 0; | |
405 | |
406 // init bit reader | |
407 init_buffer_read(); | |
408 | |
409 return 0; | |
410 } | |
411 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
412 int player_init (tta_info *info) { |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
413 unsigned int checksum; |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
414 unsigned int data_offset; |
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
415 unsigned int st_size; |
290 | 416 |
417 ttainfo = info; | |
418 | |
419 framelen = 0; | |
420 data_pos = 0; | |
421 data_cur = 0; | |
422 bitrate = 0; | |
423 | |
424 lastlen = ttainfo->DATALENGTH % ttainfo->FRAMELEN; | |
425 fframes = ttainfo->DATALENGTH / ttainfo->FRAMELEN + (lastlen ? 1:0); | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
426 st_size = (fframes + 1) * sizeof(int); |
290 | 427 |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
428 seek_table = (unsigned int *) malloc(st_size); |
290 | 429 if (!seek_table) { |
430 ttainfo->STATE = MEMORY_ERROR; | |
431 return -1; | |
432 } | |
433 | |
434 // read seek table | |
1978 | 435 if (!aud_vfs_fread(seek_table, st_size, 1, ttainfo->HANDLE)) { |
290 | 436 ttainfo->STATE = READ_ERROR; |
437 return -1; | |
438 } | |
439 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
440 checksum = crc32((unsigned char *) seek_table, st_size - sizeof(int)); |
290 | 441 st_state = (checksum == ENDSWAP_INT32(seek_table[fframes])); |
442 data_offset = sizeof(tta_hdr) + st_size; | |
443 | |
444 // init seek table | |
445 seek_table_init(seek_table, fframes, data_offset); | |
446 | |
447 // init bit reader | |
448 init_buffer_read(); | |
449 | |
450 pcm_buffer_size = PCM_BUFFER_LENGTH * ttainfo->BSIZE * ttainfo->NCH; | |
451 maxvalue = (1UL << ttainfo->BPS) - 1; | |
452 | |
453 return 0; | |
454 } | |
455 | |
456 void close_tta_file (tta_info *info) { | |
457 if (info->HANDLE) { | |
1978 | 458 aud_vfs_fclose (info->HANDLE); |
290 | 459 info->HANDLE = NULL; |
460 } | |
461 } | |
462 | |
463 void player_stop () { | |
464 if (seek_table) { | |
465 free(seek_table); | |
466 seek_table = NULL; | |
467 } | |
468 } | |
469 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
470 int get_bitrate () { |
290 | 471 return bitrate; |
472 } | |
473 | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
474 int get_samples (byte *buffer) { |
2321
6b427677621f
killed a few warnings
Cristi Magherusan <majeru@atheme.org>
parents:
2226
diff
changeset
|
475 unsigned int k, depth, unary, binary=0; |
290 | 476 byte *p = buffer; |
477 decoder *dec = tta; | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
478 int *prev = cache; |
2226 | 479 int value, value_tmp, res; |
290 | 480 |
481 for (res = 0; p < buffer + pcm_buffer_size;) { | |
482 fltst *fst = &dec->fst; | |
483 adapt *rice = &dec->rice; | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
484 int *last = &dec->last; |
290 | 485 |
486 if (data_cur == framelen) { | |
487 if (data_pos == fframes) break; | |
488 if (framelen && done_buffer_read()) { | |
489 if (set_position(data_pos) < 0) | |
490 return -1; | |
491 if (res) break; | |
492 } | |
493 | |
494 if (data_pos == fframes - 1 && lastlen) | |
495 framelen = lastlen; | |
496 else framelen = ttainfo->FRAMELEN; | |
497 | |
498 decoder_init(tta, ttainfo->NCH, ttainfo->BSIZE); | |
499 data_pos++; data_cur = 0; | |
500 } | |
501 | |
502 // decode Rice unsigned | |
503 get_unary(&unary); | |
504 | |
505 switch (unary) { | |
506 case 0: depth = 0; k = rice->k0; break; | |
507 default: | |
508 depth = 1; k = rice->k1; | |
509 unary--; | |
510 } | |
511 | |
512 if (k) { | |
513 get_binary(&binary, k); | |
514 value = (unary << k) + binary; | |
515 } else value = unary; | |
516 | |
517 switch (depth) { | |
518 case 1: | |
519 rice->sum1 += value - (rice->sum1 >> 4); | |
520 if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1]) | |
521 rice->k1--; | |
522 else if (rice->sum1 > shift_16[rice->k1 + 1]) | |
523 rice->k1++; | |
524 value += bit_shift[rice->k0]; | |
525 default: | |
526 rice->sum0 += value - (rice->sum0 >> 4); | |
527 if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0]) | |
528 rice->k0--; | |
529 else if (rice->sum0 > shift_16[rice->k0 + 1]) | |
530 rice->k0++; | |
531 } | |
2226 | 532 value_tmp = DEC(value); |
533 value = value_tmp; | |
290 | 534 |
535 // decompress stage 1: adaptive hybrid filter | |
536 hybrid_filter(fst, &value); | |
537 | |
538 // decompress stage 2: fixed order 1 prediction | |
539 switch (ttainfo->BSIZE) { | |
540 case 1: value += PREDICTOR1(*last, 4); break; // bps 8 | |
541 case 2: value += PREDICTOR1(*last, 5); break; // bps 16 | |
542 case 3: value += PREDICTOR1(*last, 5); break; // bps 24 | |
543 case 4: value += *last; break; // bps 32 | |
544 } *last = value; | |
545 | |
546 // check for errors | |
547 if (abs(value) > maxvalue) { | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
548 unsigned int tail = |
290 | 549 pcm_buffer_size / (ttainfo->BSIZE * ttainfo->NCH) - res; |
550 memset(buffer, 0, pcm_buffer_size); | |
551 data_cur += tail; res += tail; | |
552 break; | |
553 } | |
554 | |
555 if (dec < tta + (ttainfo->NCH - 1)) { | |
556 *prev++ = value; dec++; | |
557 } else { | |
558 *prev = value; | |
559 if (ttainfo->NCH > 1) { | |
551
c0f69d57483b
[svn] - change some references for long to int, reported by and patch by
nenolod
parents:
290
diff
changeset
|
560 int *r = prev - 1; |
290 | 561 for (*prev += *r/2; r >= cache; r--) |
562 *r = *(r + 1) - *r; | |
563 for (r = cache; r < prev; r++) | |
564 WRITE_BUFFER(r, ttainfo->BSIZE, p) | |
565 } | |
566 WRITE_BUFFER(prev, ttainfo->BSIZE, p) | |
567 prev = cache; | |
568 data_cur++; res++; | |
569 dec = tta; | |
570 } | |
571 } | |
572 | |
573 return res; | |
574 } | |
575 | |
576 /* end */ |