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:
parent
6b45019077
commit
5b8ed62922
3 changed files with 94 additions and 9 deletions
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}}{}{}
|
||||
|
|
Loading…
Reference in a new issue