FS#12443: Implement downmixing to stereo for multichannel flac.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31253 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Andree Buschmann 2011-12-14 18:02:57 +00:00
parent 6b45019077
commit 5b8ed62922
3 changed files with 94 additions and 9 deletions

View file

@ -27,7 +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];
static int32_t dummydec[4][MAX_BLOCKSIZE];
#define MAX_SUPPORTED_SEEKTABLE_SIZE 5000
@ -98,8 +98,7 @@ static bool flac_init(FLACContext* fc, int first_frame_offset)
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;
fc->decoded[ch] = dummydec[ch-2];
}
/* Skip any foreign tags at start of file */

View file

@ -488,6 +488,84 @@ static int decode_frame(FLACContext *s,
return 0;
}
static int flac_downmix(FLACContext *s)
{
int32_t *FL, *FR, *FC, *SB, *RL, *RR;
int32_t *outL = s->decoded[0];
int32_t *outR = s->decoded[1];
int i, scale=FLAC_OUTPUT_DEPTH-s->bps;
switch(s->channels)
{
case 3: /* 3.0 channel order: FL FR FC */
FL = s->decoded[0];
FR = s->decoded[1];
FC = s->decoded[2];
/* LF = 0.66 LF + 0.33 FC
LR = 0.66 LR + 0.33 FC */
for (i=0; i<s->blocksize; ++i) {
int32_t a = *(FL)*2 + *(FC);
int32_t b = *(FR)*2 + *(FC);
*outL++ = ((a + (a<<2))>>4) << scale; /* 1/3 ~= 5>>4 */
*outR++ = ((b + (b<<2))>>4) << scale; /* 1/3 ~= 5>>4 */
FL++; FR++; FC++;
}
break;
case 4: /* 4.0 channel order: FL FR RL RR */
FL = s->decoded[0];
FR = s->decoded[1];
RL = s->decoded[2];
RR = s->decoded[3];
/* LF = 0.50 LF + 0.50 RL + 0.00 RR
LR = 0.50 LR + 0.00 RL + 0.50 RR */
for (i=0; i<s->blocksize; ++i) {
int32_t a = *(FL) + *(RL);
int32_t b = *(FR) + *(RR);
*outL++ = (a>>1) << scale;
*outR++ = (b>>1) << scale;
FL++; FR++; RL++; RR++;
}
break;
case 5: /* 5.0 channel order: FL FR FC RL RR */
FL = s->decoded[0];
FR = s->decoded[1];
FC = s->decoded[2];
RL = s->decoded[3];
RR = s->decoded[4];
/* LF = 0.40 LF + 0.20 FC + 0.40 RL + 0.00 RR
LR = 0.40 LR + 0.20 FC + 0.00 RL + 0.40 RR */
for (i=0; i<s->blocksize; ++i) {
int32_t a = *(FL)*2 + *(FC) + *(RL)*2;
int32_t b = *(FR)*2 + *(FC) + *(RR)*2;
*outL++ = ((a + (a<<1))>>4) << scale; /* 3>>4 ~= 1/5 */
*outR++ = ((b + (b<<1))>>4) << scale; /* 3>>4 ~= 1/5 */
FL++; FR++; FC++; RL++; RR++;
}
break;
case 6: /* 5.1 channel order: FL FR FC SUB RL RR */
FL = s->decoded[0];
FR = s->decoded[1];
FC = s->decoded[2];
SB = s->decoded[3];
RL = s->decoded[4];
RR = s->decoded[5];
/* LF = 0.33 LF + 0.16 SUB + 0.16 FC + 0.33 RL + 0.00 RR
LR = 0.33 LR + 0.16 SUB + 0.16 FC + 0.00 RL + 0.33 RR */
for (i=0; i<s->blocksize; ++i) {
int32_t a = *(FL)*2 + *(SB) + *(FC) + *(RL)*2;
int32_t b = *(FR)*2 + *(SB) + *(FC) + *(RR)*2;
*outL++ = ((a + (a<<2))>>5) << scale; /* 5>>5 ~= 1/6 */
*outR++ = ((b + (b<<2))>>5) << scale; /* 5>>5 ~= 1/6 */
FL++; FR++; SB++; FC++; RL++; RR++;
}
break;
default: /* 1.0 and 2.0 do not need downmix, other formats unknown. */
return -501;
break;
}
return 0;
}
int flac_decode_frame(FLACContext *s,
uint8_t *buf, int buf_size,
void (*yield)(void))
@ -514,8 +592,8 @@ int flac_decode_frame(FLACContext *s,
#define DECORRELATE(left, right)\
for (i = 0; i < s->blocksize; i++) {\
int a = s->decoded[0][i];\
int b = s->decoded[1][i];\
int32_t a = s->decoded[0][i];\
int32_t b = s->decoded[1][i];\
s->decoded[0][i] = (left) << scale;\
s->decoded[1][i] = (right) << scale;\
}\
@ -524,7 +602,12 @@ int flac_decode_frame(FLACContext *s,
switch(s->decorrelation)
{
case INDEPENDENT:
if (s->channels <= 2) {
DECORRELATE(a, b) /* Always decorrelate exactly the two supported channels. */
} else {
if ((tmp=flac_downmix(s)) != 0)
return tmp;
}
break;
case LEFT_SIDE:
DECORRELATE(a, a-b)

View file

@ -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).\\
& Supports multichannel playback including downmixing to stereo.\\
Apple Lossless
& \fname{.m4a}, \fname{.mp4}
& \\
@ -199,6 +199,9 @@
& \\
\end{rbtabular}
\note{Free Lossless Audio multichannel tracks may not play in realtime on all devices due to CPU
performance requirements.}
\subsection{Other Codecs}
\begin{rbtabular}{\textwidth}{l>{\raggedright}p{6em}X}%
{\textbf{Format} & \textbf{Extension} & \textbf{Notes}}{}{}