Fix decoding of multichannel flac, refactor sample buffer handling and decorrelation (taken from ffmpeg sources) and add some flac details to the manual. Solves FS#12371.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31207 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
09722dd28d
commit
a6653a9bb6
4 changed files with 42 additions and 70 deletions
|
@ -27,6 +27,7 @@ CODEC_HEADER
|
|||
/* The output buffers containing the decoded samples (channels 0 and 1) */
|
||||
static int32_t decoded0[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_DECODED0;
|
||||
static int32_t decoded1[MAX_BLOCKSIZE] IBSS_ATTR;
|
||||
static int32_t dummydec[MAX_BLOCKSIZE];
|
||||
|
||||
#define MAX_SUPPORTED_SEEKTABLE_SIZE 5000
|
||||
|
||||
|
@ -80,12 +81,27 @@ static bool flac_init(FLACContext* fc, int first_frame_offset)
|
|||
uint16_t blocksize;
|
||||
int endofmetadata=0;
|
||||
uint32_t blocklength;
|
||||
int ch;
|
||||
|
||||
ci->memset(fc,0,sizeof(FLACContext));
|
||||
nseekpoints=0;
|
||||
|
||||
fc->sample_skip = 0;
|
||||
|
||||
/* Reset sample buffers */
|
||||
memset(decoded0, 0, sizeof(decoded0));
|
||||
memset(decoded1, 0, sizeof(decoded1));
|
||||
memset(dummydec, 0, sizeof(dummydec));
|
||||
|
||||
/* Set sample buffers in decoder structure */
|
||||
fc->decoded[0] = decoded0;
|
||||
fc->decoded[1] = decoded1;
|
||||
for (ch=2; ch<MAX_CHANNELS; ++ch)
|
||||
{
|
||||
/* Only channel 0 and 1 are used, the other are decoded to scratch */
|
||||
fc->decoded[ch] = dummydec;
|
||||
}
|
||||
|
||||
/* Skip any foreign tags at start of file */
|
||||
ci->seek_buffer(first_frame_offset);
|
||||
|
||||
|
@ -231,7 +247,7 @@ static bool frame_sync(FLACContext* fc) {
|
|||
/* Decode the frame to verify the frame crc and
|
||||
* fill fc with its metadata.
|
||||
*/
|
||||
if(flac_decode_frame(fc, decoded0, decoded1,
|
||||
if(flac_decode_frame(fc,
|
||||
bit_buffer, buff_size, ci->yield) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -485,7 +501,7 @@ enum codec_status codec_run(void)
|
|||
ci->seek_complete();
|
||||
}
|
||||
|
||||
if((res=flac_decode_frame(&fc,decoded0,decoded1,buf,
|
||||
if((res=flac_decode_frame(&fc,buf,
|
||||
bytesleft,ci->yield)) < 0) {
|
||||
LOGF("FLAC: Frame %d, error %d\n",frame,res);
|
||||
return CODEC_ERROR;
|
||||
|
@ -494,7 +510,7 @@ enum codec_status codec_run(void)
|
|||
frame++;
|
||||
|
||||
ci->yield();
|
||||
ci->pcmbuf_insert(&decoded0[fc.sample_skip], &decoded1[fc.sample_skip],
|
||||
ci->pcmbuf_insert(&fc.decoded[0][fc.sample_skip], &fc.decoded[1][fc.sample_skip],
|
||||
fc.blocksize - fc.sample_skip);
|
||||
|
||||
fc.sample_skip = 0;
|
||||
|
|
|
@ -381,17 +381,13 @@ static inline int decode_subframe(FLACContext *s, int channel, int32_t* decoded)
|
|||
}
|
||||
|
||||
static int decode_frame(FLACContext *s,
|
||||
int32_t* decoded0,
|
||||
int32_t* decoded1,
|
||||
void (*yield)(void)) ICODE_ATTR_FLAC;
|
||||
static int decode_frame(FLACContext *s,
|
||||
int32_t* decoded0,
|
||||
int32_t* decoded1,
|
||||
void (*yield)(void))
|
||||
{
|
||||
int blocksize_code, sample_rate_code, sample_size_code, assignment, crc8;
|
||||
int decorrelation, bps, blocksize, samplerate;
|
||||
int res;
|
||||
int res, ch;
|
||||
|
||||
blocksize_code = get_bits(&s->gb, 4);
|
||||
|
||||
|
@ -477,16 +473,10 @@ static int decode_frame(FLACContext *s,
|
|||
s->bps = bps;
|
||||
s->decorrelation= decorrelation;
|
||||
|
||||
for (ch=0; ch<s->channels; ++ch) {
|
||||
yield();
|
||||
/* subframes */
|
||||
if ((res=decode_subframe(s, 0, decoded0)) < 0)
|
||||
if ((res=decode_subframe(s, ch, s->decoded[ch])) < 0)
|
||||
return res-100;
|
||||
|
||||
yield();
|
||||
|
||||
if (s->channels==2) {
|
||||
if ((res=decode_subframe(s, 1, decoded1)) < 0)
|
||||
return res-200;
|
||||
}
|
||||
|
||||
yield();
|
||||
|
@ -499,8 +489,6 @@ static int decode_frame(FLACContext *s,
|
|||
}
|
||||
|
||||
int flac_decode_frame(FLACContext *s,
|
||||
int32_t* decoded0,
|
||||
int32_t* decoded1,
|
||||
uint8_t *buf, int buf_size,
|
||||
void (*yield)(void))
|
||||
{
|
||||
|
@ -516,7 +504,7 @@ int flac_decode_frame(FLACContext *s,
|
|||
return -41;
|
||||
}
|
||||
|
||||
if ((framesize=decode_frame(s,decoded0,decoded1,yield)) < 0){
|
||||
if ((framesize=decode_frame(s,yield)) < 0){
|
||||
s->bitstream_size=0;
|
||||
s->bitstream_index=0;
|
||||
return framesize;
|
||||
|
@ -524,60 +512,28 @@ int flac_decode_frame(FLACContext *s,
|
|||
|
||||
yield();
|
||||
|
||||
#define DECORRELATE(left, right)\
|
||||
for (i = 0; i < s->blocksize; i++) {\
|
||||
int a = s->decoded[0][i];\
|
||||
int b = s->decoded[1][i];\
|
||||
s->decoded[0][i] = (left) << scale;\
|
||||
s->decoded[1][i] = (right) << scale;\
|
||||
}\
|
||||
|
||||
scale=FLAC_OUTPUT_DEPTH-s->bps;
|
||||
switch(s->decorrelation)
|
||||
{
|
||||
case INDEPENDENT:
|
||||
if (s->channels==1) {;
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
{
|
||||
decoded0[i] = decoded0[i] << scale;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
{
|
||||
decoded0[i] = decoded0[i] << scale;
|
||||
decoded1[i] = decoded1[i] << scale;
|
||||
}
|
||||
}
|
||||
DECORRELATE(a, b) /* Always decorrelate exactly the two supported channels. */
|
||||
break;
|
||||
case LEFT_SIDE:
|
||||
//assert(s->channels == 2);
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
{
|
||||
decoded1[i] = (decoded0[i] - decoded1[i]) << scale;
|
||||
decoded0[i] = decoded0[i] << scale;
|
||||
}
|
||||
DECORRELATE(a, a-b)
|
||||
break;
|
||||
case RIGHT_SIDE:
|
||||
//assert(s->channels == 2);
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
{
|
||||
decoded0[i] = (decoded0[i] + decoded1[i]) << scale;
|
||||
decoded1[i] = decoded1[i] << scale;
|
||||
}
|
||||
DECORRELATE(a+b, a)
|
||||
break;
|
||||
case MID_SIDE:
|
||||
//assert(s->channels == 2);
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
{
|
||||
int mid, side;
|
||||
mid = decoded0[i];
|
||||
side = decoded1[i];
|
||||
|
||||
#if 1 //needs to be checked but IMHO it should be binary identical
|
||||
mid -= side>>1;
|
||||
decoded0[i] = (mid + side) << scale;
|
||||
decoded1[i] = mid << scale;
|
||||
#else
|
||||
|
||||
mid <<= 1;
|
||||
if (side & 1)
|
||||
mid++;
|
||||
decoded0[i] = ((mid + side) >> 1) << scale;
|
||||
decoded1[i] = ((mid - side) >> 1) << scale;
|
||||
#endif
|
||||
}
|
||||
DECORRELATE( (a-=b>>1) + b, a)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
#include "bitstream.h"
|
||||
|
||||
#define MAX_CHANNELS 2 /* Maximum supported channels */
|
||||
#define MAX_CHANNELS 6 /* Maximum supported channels, only left/right will be played back */
|
||||
#define MAX_BLOCKSIZE 4608 /* Maxsize in samples of one uncompressed frame */
|
||||
#define MAX_FRAMESIZE 32768 /* Maxsize in bytes of one compressed frame */
|
||||
#define MAX_FRAMESIZE 65536 /* Maxsize in bytes of one compressed frame */
|
||||
|
||||
#define FLAC_OUTPUT_DEPTH 29 /* Provide samples left-shifted to 28 bits+sign */
|
||||
|
||||
|
@ -38,11 +38,11 @@ typedef struct FLACContext {
|
|||
|
||||
int sample_skip;
|
||||
int framesize;
|
||||
|
||||
int32_t *decoded[MAX_CHANNELS];
|
||||
} FLACContext;
|
||||
|
||||
int flac_decode_frame(FLACContext *s,
|
||||
int32_t* decoded0,
|
||||
int32_t* decoded1,
|
||||
uint8_t *buf, int buf_size,
|
||||
void (*yield)(void)) ICODE_ATTR_FLAC;
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@
|
|||
& Linear PCM 8/16/24/32 bit, IEEE float 32/64 bit, ITU-T G.711 a-law/$\mu$-law\\
|
||||
Free Lossless Audio
|
||||
& \fname{.flac}
|
||||
& \\
|
||||
& Supports multichannel tracks w/o downmixing (only left/right is played).\\
|
||||
Apple Lossless
|
||||
& \fname{.m4a}, \fname{.mp4}
|
||||
& \\
|
||||
|
|
Loading…
Reference in a new issue