summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohamed Tarek <mt@rockbox.org>2009-08-04 13:54:06 +0000
committerMohamed Tarek <mt@rockbox.org>2009-08-04 13:54:06 +0000
commit26cee86a0ca354ac15d46fb92db0cc9a776dd4b2 (patch)
tree2b06da998cff4e4cdfcd7545b6d616116ec947e5
parent7996e773340698a6d8c7bcdc465b8a9245f65601 (diff)
downloadrockbox-26cee86a0ca354ac15d46fb92db0cc9a776dd4b2.tar.gz
rockbox-26cee86a0ca354ac15d46fb92db0cc9a776dd4b2.zip
Add support for AC3 audio in RM container.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22155 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/SOURCES1
-rw-r--r--apps/codecs/codecs.make1
-rw-r--r--apps/codecs/dnet.c190
-rw-r--r--apps/codecs/librm/rm.c14
-rw-r--r--apps/codecs/librm/rm.h7
-rw-r--r--apps/metadata.c3
-rw-r--r--apps/metadata.h1
-rw-r--r--apps/metadata/rm.c22
8 files changed, 231 insertions, 8 deletions
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index dc6819d272..92e4d2d254 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -11,6 +11,7 @@ alac.c
11#endif 11#endif
12cook.c 12cook.c
13raac.c 13raac.c
14dnet.c
14mpc.c 15mpc.c
15wma.c 16wma.c
16sid.c 17sid.c
diff --git a/apps/codecs/codecs.make b/apps/codecs/codecs.make
index b327bd7c69..41f5bdccd1 100644
--- a/apps/codecs/codecs.make
+++ b/apps/codecs/codecs.make
@@ -77,6 +77,7 @@ $(CODECDIR)/wavpack_enc.codec: $(CODECDIR)/libwavpack.a
77$(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a 77$(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a
78$(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a $(CODECDIR)/librm.a 78$(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a $(CODECDIR)/librm.a
79$(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a 79$(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a
80$(CODECDIR)/dnet.codec : $(CODECDIR)/liba52.a $(CODECDIR)/librm.a
80 81
81$(CODECS): $(CODECLIB) # this must be last in codec dependency list 82$(CODECS): $(CODECLIB) # this must be last in codec dependency list
82 83
diff --git a/apps/codecs/dnet.c b/apps/codecs/dnet.c
new file mode 100644
index 0000000000..12352ed903
--- /dev/null
+++ b/apps/codecs/dnet.c
@@ -0,0 +1,190 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id:$
9 *
10 * Copyright (C) 2009 Mohamed Tarek
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "codeclib.h"
23#include <codecs/librm/rm.h>
24#include <inttypes.h> /* Needed by a52.h */
25#include <codecs/liba52/config-a52.h>
26#include <codecs/liba52/a52.h>
27
28CODEC_HEADER
29
30#define BUFFER_SIZE 4096
31
32#define A52_SAMPLESPERFRAME (6*256)
33
34static a52_state_t *state;
35unsigned long samplesdone;
36unsigned long frequency;
37RMContext rmctx;
38RMPacket pkt;
39
40static void init_rm(RMContext *rmctx)
41{
42 memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
43}
44
45/* used outside liba52 */
46static uint8_t buf[3840] IBSS_ATTR;
47
48static inline void output_audio(sample_t *samples)
49{
50 ci->yield();
51 ci->pcmbuf_insert(&samples[0], &samples[256], 256);
52}
53
54static void a52_decode_data(uint8_t *start, uint8_t *end)
55{
56 static uint8_t *bufptr = buf;
57 static uint8_t *bufpos = buf + 7;
58 /*
59 * sample_rate and flags are static because this routine could
60 * exit between the a52_syncinfo() and the ao_setup(), and we want
61 * to have the same values when we get back !
62 */
63 static int sample_rate;
64 static int flags;
65 int bit_rate;
66 int len;
67
68 while (1) {
69 len = end - start;
70 if (!len)
71 break;
72 if (len > bufpos - bufptr)
73 len = bufpos - bufptr;
74 memcpy(bufptr, start, len);
75 bufptr += len;
76 start += len;
77 if (bufptr == bufpos) {
78 if (bufpos == buf + 7) {
79 int length;
80
81 length = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
82 if (!length) {
83 //DEBUGF("skip\n");
84 for (bufptr = buf; bufptr < buf + 6; bufptr++)
85 bufptr[0] = bufptr[1];
86 continue;
87 }
88 bufpos = buf + length;
89 } else {
90 /* Unity gain is 1 << 26, and we want to end up on 28 bits
91 of precision instead of the default 30.
92 */
93 level_t level = 1 << 24;
94 sample_t bias = 0;
95 int i;
96
97 /* This is the configuration for the downmixing: */
98 flags = A52_STEREO | A52_ADJUST_LEVEL;
99
100 if (a52_frame(state, buf, &flags, &level, bias))
101 goto error;
102 a52_dynrng(state, NULL, NULL);
103 frequency = sample_rate;
104
105 /* An A52 frame consists of 6 blocks of 256 samples
106 So we decode and output them one block at a time */
107 for (i = 0; i < 6; i++) {
108 if (a52_block(state))
109 goto error;
110 output_audio(a52_samples(state));
111 samplesdone += 256;
112 }
113 ci->set_elapsed(samplesdone/(frequency/1000));
114 bufptr = buf;
115 bufpos = buf + 7;
116 continue;
117 error:
118 //logf("Error decoding A52 stream\n");
119 bufptr = buf;
120 bufpos = buf + 7;
121 }
122 }
123 }
124}
125
126
127/* this is the codec entry point */
128enum codec_status codec_main(void)
129{
130 size_t n;
131 uint8_t *filebuf;
132 int retval, consumed, packet_offset;
133
134 /* Generic codec initialisation */
135 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
136 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
137
138next_track:
139 if (codec_init()) {
140 retval = CODEC_ERROR;
141 goto exit;
142 }
143
144 while (!ci->taginfo_ready)
145 ci->yield();
146
147 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
148 codec_set_replaygain(ci->id3);
149
150 /* Intializations */
151 state = a52_init(0);
152 ci->memset(&rmctx,0,sizeof(RMContext));
153 ci->memset(&pkt,0,sizeof(RMPacket));
154 init_rm(&rmctx);
155
156 /* Seek to the first packet */
157 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE );
158
159 /* The main decoding loop */
160 while(pkt.timestamp < rmctx.duration) {
161 ci->yield();
162 if (ci->stop_codec || ci->new_track)
163 break;
164
165 if (ci->seek_time) {
166 packet_offset = ci->seek_time / (((rmctx.block_align + PACKET_HEADER_SIZE)*8*1000)/rmctx.bit_rate);
167 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE));
168 samplesdone = A52_SAMPLESPERFRAME * packet_offset;
169 ci->seek_complete();
170 }
171
172 filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE);
173 consumed = rm_get_packet(&filebuf, &rmctx, &pkt);
174 if(consumed < 0) {
175 DEBUGF("rm_get_packet failed\n");
176 return CODEC_ERROR;
177 }
178 a52_decode_data(filebuf, filebuf + rmctx.block_align);
179 ci->advance_buffer(pkt.length);
180 }
181
182 retval = CODEC_OK;
183
184 if (ci->request_next_track())
185 goto next_track;
186
187exit:
188 a52_free(state);
189 return retval;
190}
diff --git a/apps/codecs/librm/rm.c b/apps/codecs/librm/rm.c
index c802a0c5a9..b205e7f88d 100644
--- a/apps/codecs/librm/rm.c
+++ b/apps/codecs/librm/rm.c
@@ -27,6 +27,8 @@
27#include "codeclib.h" 27#include "codeclib.h"
28#endif 28#endif
29 29
30#define SWAP(a, b) do{uint8_t SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
31
30void advance_buffer(uint8_t **buf, int val) 32void advance_buffer(uint8_t **buf, int val)
31{ 33{
32 *buf += val; 34 *buf += val;
@@ -464,7 +466,6 @@ void rm_get_packet_fd(int fd,RMContext *rmctx, RMPacket *pkt)
464 " stream = %d\n" 466 " stream = %d\n"
465 " timestmp= %d\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp); 467 " timestmp= %d\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp);
466 468
467 //getchar();
468 if(pkt->version == 0) 469 if(pkt->version == 0)
469 { 470 {
470 read_uint8(fd,&packet_group); 471 read_uint8(fd,&packet_group);
@@ -550,7 +551,16 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
550 } 551 }
551 rmctx->audio_pkt_cnt = --rmctx->sub_packet_cnt; 552 rmctx->audio_pkt_cnt = --rmctx->sub_packet_cnt;
552 } 553 }
553 } 554 }
555
556 else if (rmctx->codec_type == CODEC_AC3) {
557 /* The byte order of the data is reversed from standard AC3 */
558 for(x = 0; x < pkt->length - PACKET_HEADER_SIZE; x+=2) {
559 SWAP((*src)[0], (*src)[1]);
560 *src += 2;
561 }
562 *src -= x;
563 }
554 rmctx->audio_pkt_cnt++; 564 rmctx->audio_pkt_cnt++;
555 }while(++(rmctx->sub_packet_cnt) < h); 565 }while(++(rmctx->sub_packet_cnt) < h);
556 566
diff --git a/apps/codecs/librm/rm.h b/apps/codecs/librm/rm.h
index 12e9b18fa3..86fe5e7f1a 100644
--- a/apps/codecs/librm/rm.h
+++ b/apps/codecs/librm/rm.h
@@ -28,7 +28,12 @@
28#define DATA_HEADER_SIZE 18 28#define DATA_HEADER_SIZE 18
29#define PACKET_HEADER_SIZE 12 29#define PACKET_HEADER_SIZE 12
30 30
31enum codecs{CODEC_COOK, CODEC_AAC}; 31enum codecs {
32 CODEC_COOK,
33 CODEC_AAC,
34 CODEC_AC3
35};
36
32typedef struct rm_packet 37typedef struct rm_packet
33{ 38{
34 uint8_t *frames[100]; /* Pointers to ordered audio frames in buffer */ 39 uint8_t *frames[100]; /* Pointers to ordered audio frames in buffer */
diff --git a/apps/metadata.c b/apps/metadata.c
index f227776c0a..63547646ca 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -121,6 +121,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
121 /* AAC in RM/RA */ 121 /* AAC in RM/RA */
122 [AFMT_RM_AAC] = 122 [AFMT_RM_AAC] =
123 AFMT_ENTRY("RAAC", "raac", NULL, "rm\0ra\0rmvb\0" ), 123 AFMT_ENTRY("RAAC", "raac", NULL, "rm\0ra\0rmvb\0" ),
124 /* AC3 in RM/RA */
125 [AFMT_RM_AC3] =
126 AFMT_ENTRY("AC3", "dnet", NULL, "rm\0ra\0rmvb\0" ),
124#endif 127#endif
125}; 128};
126 129
diff --git a/apps/metadata.h b/apps/metadata.h
index cefc6c3945..c43d2c2260 100644
--- a/apps/metadata.h
+++ b/apps/metadata.h
@@ -63,6 +63,7 @@ enum
63 AFMT_SAP, /* Amiga 8Bit SAP Format */ 63 AFMT_SAP, /* Amiga 8Bit SAP Format */
64 AFMT_RM_COOK, /* Cook in RM/RA */ 64 AFMT_RM_COOK, /* Cook in RM/RA */
65 AFMT_RM_AAC, /* AAC in RM/RA */ 65 AFMT_RM_AAC, /* AAC in RM/RA */
66 AFMT_RM_AC3, /* AC3 in RM/RA */
66#endif 67#endif
67 68
68 /* add new formats at any index above this line to have a sensible order - 69 /* add new formats at any index above this line to have a sensible order -
diff --git a/apps/metadata/rm.c b/apps/metadata/rm.c
index 4be0de647f..c74acef5dd 100644
--- a/apps/metadata/rm.c
+++ b/apps/metadata/rm.c
@@ -160,24 +160,32 @@ static inline int real_read_audio_stream_info(int fd, RMContext *rmctx)
160 skipped += 1; 160 skipped += 1;
161 } 161 }
162 162
163 read_uint32be(fd, &rmctx->extradata_size);
164 skipped += 4;
165 read(fd, rmctx->codec_extradata, rmctx->extradata_size);
166 skipped += rmctx->extradata_size;
167 switch(fourcc) { 163 switch(fourcc) {
168 case FOURCC('c','o','o','k'): 164 case FOURCC('c','o','o','k'):
169 rmctx->codec_type = CODEC_COOK; 165 rmctx->codec_type = CODEC_COOK;
166 read_uint32be(fd, &rmctx->extradata_size);
167 skipped += 4;
168 read(fd, rmctx->codec_extradata, rmctx->extradata_size);
169 skipped += rmctx->extradata_size;
170 break; 170 break;
171 171
172 case FOURCC('r','a','a','c'): 172 case FOURCC('r','a','a','c'):
173 case FOURCC('r','a','c','p'): 173 case FOURCC('r','a','c','p'):
174 rmctx->codec_type = CODEC_AAC; 174 rmctx->codec_type = CODEC_AAC;
175 read_uint32be(fd, &rmctx->extradata_size);
176 skipped += 4;
177 read(fd, rmctx->codec_extradata, rmctx->extradata_size);
178 skipped += rmctx->extradata_size;
179 break;
180
181 case FOURCC('d','n','e','t'):
182 rmctx->codec_type = CODEC_AC3;
175 break; 183 break;
176 184
177 default: /* Not a supported codec */ 185 default: /* Not a supported codec */
178 return -1; 186 return -1;
179 } 187 }
180 188
181 DEBUGF(" flavor = %d\n",flavor); 189 DEBUGF(" flavor = %d\n",flavor);
182 DEBUGF(" coded_frame_size = %ld\n",coded_framesize); 190 DEBUGF(" coded_frame_size = %ld\n",coded_framesize);
183 DEBUGF(" sub_packet_h = %d\n",rmctx->sub_packet_h); 191 DEBUGF(" sub_packet_h = %d\n",rmctx->sub_packet_h);
@@ -407,6 +415,10 @@ bool get_rm_metadata(int fd, struct mp3entry* id3)
407 case CODEC_AAC: 415 case CODEC_AAC:
408 id3->codectype = AFMT_RM_AAC; 416 id3->codectype = AFMT_RM_AAC;
409 break; 417 break;
418
419 case CODEC_AC3:
420 id3->codectype = AFMT_RM_AC3;
421 break;
410 } 422 }
411 423
412 id3->bitrate = rmctx->bit_rate / 1000; 424 id3->bitrate = rmctx->bit_rate / 1000;