forked from len0rd/rockbox
Add support for AC3 audio in RM container.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22155 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
7996e77334
commit
26cee86a0c
8 changed files with 231 additions and 8 deletions
|
|
@ -11,6 +11,7 @@ alac.c
|
|||
#endif
|
||||
cook.c
|
||||
raac.c
|
||||
dnet.c
|
||||
mpc.c
|
||||
wma.c
|
||||
sid.c
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ $(CODECDIR)/wavpack_enc.codec: $(CODECDIR)/libwavpack.a
|
|||
$(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a
|
||||
$(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a $(CODECDIR)/librm.a
|
||||
$(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a
|
||||
$(CODECDIR)/dnet.codec : $(CODECDIR)/liba52.a $(CODECDIR)/librm.a
|
||||
|
||||
$(CODECS): $(CODECLIB) # this must be last in codec dependency list
|
||||
|
||||
|
|
|
|||
190
apps/codecs/dnet.c
Normal file
190
apps/codecs/dnet.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id:$
|
||||
*
|
||||
* Copyright (C) 2009 Mohamed Tarek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "codeclib.h"
|
||||
#include <codecs/librm/rm.h>
|
||||
#include <inttypes.h> /* Needed by a52.h */
|
||||
#include <codecs/liba52/config-a52.h>
|
||||
#include <codecs/liba52/a52.h>
|
||||
|
||||
CODEC_HEADER
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
#define A52_SAMPLESPERFRAME (6*256)
|
||||
|
||||
static a52_state_t *state;
|
||||
unsigned long samplesdone;
|
||||
unsigned long frequency;
|
||||
RMContext rmctx;
|
||||
RMPacket pkt;
|
||||
|
||||
static void init_rm(RMContext *rmctx)
|
||||
{
|
||||
memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
|
||||
}
|
||||
|
||||
/* used outside liba52 */
|
||||
static uint8_t buf[3840] IBSS_ATTR;
|
||||
|
||||
static inline void output_audio(sample_t *samples)
|
||||
{
|
||||
ci->yield();
|
||||
ci->pcmbuf_insert(&samples[0], &samples[256], 256);
|
||||
}
|
||||
|
||||
static void a52_decode_data(uint8_t *start, uint8_t *end)
|
||||
{
|
||||
static uint8_t *bufptr = buf;
|
||||
static uint8_t *bufpos = buf + 7;
|
||||
/*
|
||||
* sample_rate and flags are static because this routine could
|
||||
* exit between the a52_syncinfo() and the ao_setup(), and we want
|
||||
* to have the same values when we get back !
|
||||
*/
|
||||
static int sample_rate;
|
||||
static int flags;
|
||||
int bit_rate;
|
||||
int len;
|
||||
|
||||
while (1) {
|
||||
len = end - start;
|
||||
if (!len)
|
||||
break;
|
||||
if (len > bufpos - bufptr)
|
||||
len = bufpos - bufptr;
|
||||
memcpy(bufptr, start, len);
|
||||
bufptr += len;
|
||||
start += len;
|
||||
if (bufptr == bufpos) {
|
||||
if (bufpos == buf + 7) {
|
||||
int length;
|
||||
|
||||
length = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
|
||||
if (!length) {
|
||||
//DEBUGF("skip\n");
|
||||
for (bufptr = buf; bufptr < buf + 6; bufptr++)
|
||||
bufptr[0] = bufptr[1];
|
||||
continue;
|
||||
}
|
||||
bufpos = buf + length;
|
||||
} else {
|
||||
/* Unity gain is 1 << 26, and we want to end up on 28 bits
|
||||
of precision instead of the default 30.
|
||||
*/
|
||||
level_t level = 1 << 24;
|
||||
sample_t bias = 0;
|
||||
int i;
|
||||
|
||||
/* This is the configuration for the downmixing: */
|
||||
flags = A52_STEREO | A52_ADJUST_LEVEL;
|
||||
|
||||
if (a52_frame(state, buf, &flags, &level, bias))
|
||||
goto error;
|
||||
a52_dynrng(state, NULL, NULL);
|
||||
frequency = sample_rate;
|
||||
|
||||
/* An A52 frame consists of 6 blocks of 256 samples
|
||||
So we decode and output them one block at a time */
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (a52_block(state))
|
||||
goto error;
|
||||
output_audio(a52_samples(state));
|
||||
samplesdone += 256;
|
||||
}
|
||||
ci->set_elapsed(samplesdone/(frequency/1000));
|
||||
bufptr = buf;
|
||||
bufpos = buf + 7;
|
||||
continue;
|
||||
error:
|
||||
//logf("Error decoding A52 stream\n");
|
||||
bufptr = buf;
|
||||
bufpos = buf + 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* this is the codec entry point */
|
||||
enum codec_status codec_main(void)
|
||||
{
|
||||
size_t n;
|
||||
uint8_t *filebuf;
|
||||
int retval, consumed, packet_offset;
|
||||
|
||||
/* Generic codec initialisation */
|
||||
ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
|
||||
ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
|
||||
|
||||
next_track:
|
||||
if (codec_init()) {
|
||||
retval = CODEC_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while (!ci->taginfo_ready)
|
||||
ci->yield();
|
||||
|
||||
ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
|
||||
codec_set_replaygain(ci->id3);
|
||||
|
||||
/* Intializations */
|
||||
state = a52_init(0);
|
||||
ci->memset(&rmctx,0,sizeof(RMContext));
|
||||
ci->memset(&pkt,0,sizeof(RMPacket));
|
||||
init_rm(&rmctx);
|
||||
|
||||
/* Seek to the first packet */
|
||||
ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE );
|
||||
|
||||
/* The main decoding loop */
|
||||
while(pkt.timestamp < rmctx.duration) {
|
||||
ci->yield();
|
||||
if (ci->stop_codec || ci->new_track)
|
||||
break;
|
||||
|
||||
if (ci->seek_time) {
|
||||
packet_offset = ci->seek_time / (((rmctx.block_align + PACKET_HEADER_SIZE)*8*1000)/rmctx.bit_rate);
|
||||
ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE));
|
||||
samplesdone = A52_SAMPLESPERFRAME * packet_offset;
|
||||
ci->seek_complete();
|
||||
}
|
||||
|
||||
filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE);
|
||||
consumed = rm_get_packet(&filebuf, &rmctx, &pkt);
|
||||
if(consumed < 0) {
|
||||
DEBUGF("rm_get_packet failed\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
a52_decode_data(filebuf, filebuf + rmctx.block_align);
|
||||
ci->advance_buffer(pkt.length);
|
||||
}
|
||||
|
||||
retval = CODEC_OK;
|
||||
|
||||
if (ci->request_next_track())
|
||||
goto next_track;
|
||||
|
||||
exit:
|
||||
a52_free(state);
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -27,6 +27,8 @@
|
|||
#include "codeclib.h"
|
||||
#endif
|
||||
|
||||
#define SWAP(a, b) do{uint8_t SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
|
||||
|
||||
void advance_buffer(uint8_t **buf, int val)
|
||||
{
|
||||
*buf += val;
|
||||
|
|
@ -464,7 +466,6 @@ void rm_get_packet_fd(int fd,RMContext *rmctx, RMPacket *pkt)
|
|||
" stream = %d\n"
|
||||
" timestmp= %d\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp);
|
||||
|
||||
//getchar();
|
||||
if(pkt->version == 0)
|
||||
{
|
||||
read_uint8(fd,&packet_group);
|
||||
|
|
@ -551,6 +552,15 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
|
|||
rmctx->audio_pkt_cnt = --rmctx->sub_packet_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
else if (rmctx->codec_type == CODEC_AC3) {
|
||||
/* The byte order of the data is reversed from standard AC3 */
|
||||
for(x = 0; x < pkt->length - PACKET_HEADER_SIZE; x+=2) {
|
||||
SWAP((*src)[0], (*src)[1]);
|
||||
*src += 2;
|
||||
}
|
||||
*src -= x;
|
||||
}
|
||||
rmctx->audio_pkt_cnt++;
|
||||
}while(++(rmctx->sub_packet_cnt) < h);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,12 @@
|
|||
#define DATA_HEADER_SIZE 18
|
||||
#define PACKET_HEADER_SIZE 12
|
||||
|
||||
enum codecs{CODEC_COOK, CODEC_AAC};
|
||||
enum codecs {
|
||||
CODEC_COOK,
|
||||
CODEC_AAC,
|
||||
CODEC_AC3
|
||||
};
|
||||
|
||||
typedef struct rm_packet
|
||||
{
|
||||
uint8_t *frames[100]; /* Pointers to ordered audio frames in buffer */
|
||||
|
|
|
|||
|
|
@ -121,6 +121,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
|||
/* AAC in RM/RA */
|
||||
[AFMT_RM_AAC] =
|
||||
AFMT_ENTRY("RAAC", "raac", NULL, "rm\0ra\0rmvb\0" ),
|
||||
/* AC3 in RM/RA */
|
||||
[AFMT_RM_AC3] =
|
||||
AFMT_ENTRY("AC3", "dnet", NULL, "rm\0ra\0rmvb\0" ),
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ enum
|
|||
AFMT_SAP, /* Amiga 8Bit SAP Format */
|
||||
AFMT_RM_COOK, /* Cook in RM/RA */
|
||||
AFMT_RM_AAC, /* AAC in RM/RA */
|
||||
AFMT_RM_AC3, /* AC3 in RM/RA */
|
||||
#endif
|
||||
|
||||
/* add new formats at any index above this line to have a sensible order -
|
||||
|
|
|
|||
|
|
@ -160,18 +160,26 @@ static inline int real_read_audio_stream_info(int fd, RMContext *rmctx)
|
|||
skipped += 1;
|
||||
}
|
||||
|
||||
switch(fourcc) {
|
||||
case FOURCC('c','o','o','k'):
|
||||
rmctx->codec_type = CODEC_COOK;
|
||||
read_uint32be(fd, &rmctx->extradata_size);
|
||||
skipped += 4;
|
||||
read(fd, rmctx->codec_extradata, rmctx->extradata_size);
|
||||
skipped += rmctx->extradata_size;
|
||||
switch(fourcc) {
|
||||
case FOURCC('c','o','o','k'):
|
||||
rmctx->codec_type = CODEC_COOK;
|
||||
break;
|
||||
|
||||
case FOURCC('r','a','a','c'):
|
||||
case FOURCC('r','a','c','p'):
|
||||
rmctx->codec_type = CODEC_AAC;
|
||||
read_uint32be(fd, &rmctx->extradata_size);
|
||||
skipped += 4;
|
||||
read(fd, rmctx->codec_extradata, rmctx->extradata_size);
|
||||
skipped += rmctx->extradata_size;
|
||||
break;
|
||||
|
||||
case FOURCC('d','n','e','t'):
|
||||
rmctx->codec_type = CODEC_AC3;
|
||||
break;
|
||||
|
||||
default: /* Not a supported codec */
|
||||
|
|
@ -407,6 +415,10 @@ bool get_rm_metadata(int fd, struct mp3entry* id3)
|
|||
case CODEC_AAC:
|
||||
id3->codectype = AFMT_RM_AAC;
|
||||
break;
|
||||
|
||||
case CODEC_AC3:
|
||||
id3->codectype = AFMT_RM_AC3;
|
||||
break;
|
||||
}
|
||||
|
||||
id3->bitrate = rmctx->bit_rate / 1000;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue