diff options
author | Dave Chapman <dave@dchapman.com> | 2005-06-11 10:08:17 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2005-06-11 10:08:17 +0000 |
commit | 55ed7d7214684d53c38eb4fe293249e5d3e0ac91 (patch) | |
tree | 26432321890d0e8d616b7257807e31a2b8cc7cdd /apps/plugins/codeca52.c | |
parent | c82518ce060d3da4800bcc08fffe910b37711f38 (diff) | |
download | rockbox-55ed7d7214684d53c38eb4fe293249e5d3e0ac91.tar.gz rockbox-55ed7d7214684d53c38eb4fe293249e5d3e0ac91.zip |
First codeca52 (A52 aka AC3 playback) - it is already faster than realtime, with zero optimisations
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6668 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/codeca52.c')
-rw-r--r-- | apps/plugins/codeca52.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/apps/plugins/codeca52.c b/apps/plugins/codeca52.c new file mode 100644 index 0000000000..5cb27defc8 --- /dev/null +++ b/apps/plugins/codeca52.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Dave Chapman | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "plugin.h" | ||
21 | |||
22 | #include <inttypes.h> /* Needed by a52.h */ | ||
23 | #include <codecs/liba52/config-a52.h> | ||
24 | #include <codecs/liba52/a52.h> | ||
25 | |||
26 | #include "playback.h" | ||
27 | #include "lib/codeclib.h" | ||
28 | |||
29 | #define BUFFER_SIZE 4096 | ||
30 | |||
31 | struct plugin_api* rb; | ||
32 | struct codec_api* ci; | ||
33 | |||
34 | static float gain = 1; | ||
35 | static a52_state_t * state; | ||
36 | unsigned long samplesdone; | ||
37 | unsigned long frequency; | ||
38 | |||
39 | /* A post-processing buffer used outside liba52 */ | ||
40 | static uint8_t buf[3840] IDATA_ATTR; | ||
41 | |||
42 | static inline int16_t convert (int32_t i) | ||
43 | { | ||
44 | i >>= 15; | ||
45 | return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i); | ||
46 | } | ||
47 | |||
48 | void output_audio(sample_t* samples,int flags) { | ||
49 | int i; | ||
50 | static int16_t int16_samples[256*2]; | ||
51 | |||
52 | flags &= A52_CHANNEL_MASK | A52_LFE; | ||
53 | |||
54 | if (flags==A52_STEREO) { | ||
55 | for (i = 0; i < 256; i++) { | ||
56 | int16_samples[2*i] = convert (samples[i]); | ||
57 | int16_samples[2*i+1] = convert (samples[i+256]); | ||
58 | } | ||
59 | } else { | ||
60 | DEBUGF("ERROR: unsupported format: %d\n",flags); | ||
61 | } | ||
62 | |||
63 | rb->yield(); | ||
64 | while(!ci->audiobuffer_insert((unsigned char*)int16_samples,256*2*2)) | ||
65 | rb->yield(); | ||
66 | } | ||
67 | |||
68 | |||
69 | void a52_decode_data (uint8_t * start, uint8_t * end) | ||
70 | { | ||
71 | static uint8_t * bufptr = buf; | ||
72 | static uint8_t * bufpos = buf + 7; | ||
73 | |||
74 | /* | ||
75 | * sample_rate and flags are static because this routine could | ||
76 | * exit between the a52_syncinfo() and the ao_setup(), and we want | ||
77 | * to have the same values when we get back ! | ||
78 | */ | ||
79 | |||
80 | static int sample_rate; | ||
81 | static int flags; | ||
82 | int bit_rate; | ||
83 | int len; | ||
84 | |||
85 | while (1) { | ||
86 | len = end - start; | ||
87 | if (!len) | ||
88 | break; | ||
89 | if (len > bufpos - bufptr) | ||
90 | len = bufpos - bufptr; | ||
91 | memcpy (bufptr, start, len); | ||
92 | bufptr += len; | ||
93 | start += len; | ||
94 | if (bufptr == bufpos) { | ||
95 | if (bufpos == buf + 7) { | ||
96 | int length; | ||
97 | |||
98 | length = a52_syncinfo (buf, &flags, &sample_rate, &bit_rate); | ||
99 | if (!length) { | ||
100 | DEBUGF("skip\n"); | ||
101 | for (bufptr = buf; bufptr < buf + 6; bufptr++) | ||
102 | bufptr[0] = bufptr[1]; | ||
103 | continue; | ||
104 | } | ||
105 | bufpos = buf + length; | ||
106 | } else { | ||
107 | // The following two defaults are taken from audio_out_oss.c: | ||
108 | level_t level; | ||
109 | sample_t bias; | ||
110 | int i; | ||
111 | |||
112 | /* This is the configuration for the downmixing: */ | ||
113 | flags=A52_STEREO|A52_ADJUST_LEVEL|A52_LFE; | ||
114 | level=(1 << 26); | ||
115 | bias=0; | ||
116 | |||
117 | level = (level_t) (level * gain); | ||
118 | |||
119 | if (a52_frame (state, buf, &flags, &level, bias)) { | ||
120 | goto error; | ||
121 | } | ||
122 | |||
123 | // file_info->frames_decoded++; | ||
124 | |||
125 | // /* We assume this never changes */ | ||
126 | // file_info->samplerate=sample_rate; | ||
127 | frequency=sample_rate; | ||
128 | |||
129 | // An A52 frame consists of 6 blocks of 256 samples | ||
130 | // So we decode and output them one block at a time | ||
131 | for (i = 0; i < 6; i++) { | ||
132 | if (a52_block (state)) { | ||
133 | goto error; | ||
134 | } | ||
135 | |||
136 | output_audio(a52_samples (state),flags); | ||
137 | samplesdone+=256; | ||
138 | } | ||
139 | ci->set_elapsed(samplesdone/(frequency/1000)); | ||
140 | bufptr = buf; | ||
141 | bufpos = buf + 7; | ||
142 | continue; | ||
143 | |||
144 | error: | ||
145 | |||
146 | //logf("Error decoding A52 stream\n"); | ||
147 | bufptr = buf; | ||
148 | bufpos = buf + 7; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | |||
154 | #ifndef SIMULATOR | ||
155 | extern char iramcopy[]; | ||
156 | extern char iramstart[]; | ||
157 | extern char iramend[]; | ||
158 | #endif | ||
159 | |||
160 | /* this is the plugin entry point */ | ||
161 | enum plugin_status plugin_start(struct plugin_api* api, void* parm) | ||
162 | { | ||
163 | size_t n; | ||
164 | unsigned char* filebuf; | ||
165 | |||
166 | /* Generic plugin initialisation */ | ||
167 | TEST_PLUGIN_API(api); | ||
168 | |||
169 | rb = api; | ||
170 | ci = (struct codec_api*)parm; | ||
171 | |||
172 | #ifndef SIMULATOR | ||
173 | rb->memcpy(iramstart, iramcopy, iramend-iramstart); | ||
174 | #endif | ||
175 | |||
176 | ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); | ||
177 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); | ||
178 | |||
179 | next_track: | ||
180 | |||
181 | if (codec_init(api, ci)) { | ||
182 | return PLUGIN_ERROR; | ||
183 | } | ||
184 | |||
185 | /* Intialise the A52 decoder and check for success */ | ||
186 | state = a52_init (0); // Parameter is "accel" | ||
187 | |||
188 | /* The main decoding loop */ | ||
189 | |||
190 | samplesdone=0; | ||
191 | while (1) { | ||
192 | if (ci->stop_codec || ci->reload_codec) { | ||
193 | break; | ||
194 | } | ||
195 | |||
196 | filebuf=ci->request_buffer(&n,BUFFER_SIZE); | ||
197 | |||
198 | if (n==0) { /* End of Stream */ | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | a52_decode_data(filebuf,filebuf+n); | ||
203 | |||
204 | ci->advance_buffer(n); | ||
205 | } | ||
206 | |||
207 | if (ci->request_next_track()) | ||
208 | goto next_track; | ||
209 | |||
210 | //NOT NEEDED??: a52_free (state); | ||
211 | |||
212 | return PLUGIN_OK; | ||
213 | } | ||