summaryrefslogtreecommitdiff
path: root/apps/plugins/codeca52.c
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2005-06-11 10:08:17 +0000
committerDave Chapman <dave@dchapman.com>2005-06-11 10:08:17 +0000
commit55ed7d7214684d53c38eb4fe293249e5d3e0ac91 (patch)
tree26432321890d0e8d616b7257807e31a2b8cc7cdd /apps/plugins/codeca52.c
parentc82518ce060d3da4800bcc08fffe910b37711f38 (diff)
downloadrockbox-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.c213
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
31struct plugin_api* rb;
32struct codec_api* ci;
33
34static float gain = 1;
35static a52_state_t * state;
36unsigned long samplesdone;
37unsigned long frequency;
38
39/* A post-processing buffer used outside liba52 */
40static uint8_t buf[3840] IDATA_ATTR;
41
42static inline int16_t convert (int32_t i)
43{
44 i >>= 15;
45 return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i);
46}
47
48void 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
69void 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
155extern char iramcopy[];
156extern char iramstart[];
157extern char iramend[];
158#endif
159
160/* this is the plugin entry point */
161enum 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}