forked from len0rd/rockbox
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) */
|
/* The output buffers containing the decoded samples (channels 0 and 1) */
|
||||||
static int32_t decoded0[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_DECODED0;
|
static int32_t decoded0[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_DECODED0;
|
||||||
static int32_t decoded1[MAX_BLOCKSIZE] IBSS_ATTR;
|
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
|
#define MAX_SUPPORTED_SEEKTABLE_SIZE 5000
|
||||||
|
|
||||||
|
@ -98,8 +98,7 @@ static bool flac_init(FLACContext* fc, int first_frame_offset)
|
||||||
fc->decoded[1] = decoded1;
|
fc->decoded[1] = decoded1;
|
||||||
for (ch=2; ch<MAX_CHANNELS; ++ch)
|
for (ch=2; ch<MAX_CHANNELS; ++ch)
|
||||||
{
|
{
|
||||||
/* Only channel 0 and 1 are used, the other are decoded to scratch */
|
fc->decoded[ch] = dummydec[ch-2];
|
||||||
fc->decoded[ch] = dummydec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip any foreign tags at start of file */
|
/* Skip any foreign tags at start of file */
|
||||||
|
|
|
@ -488,9 +488,87 @@ static int decode_frame(FLACContext *s,
|
||||||
return 0;
|
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,
|
int flac_decode_frame(FLACContext *s,
|
||||||
uint8_t *buf, int buf_size,
|
uint8_t *buf, int buf_size,
|
||||||
void (*yield)(void))
|
void (*yield)(void))
|
||||||
{
|
{
|
||||||
int tmp;
|
int tmp;
|
||||||
int i;
|
int i;
|
||||||
|
@ -514,8 +592,8 @@ int flac_decode_frame(FLACContext *s,
|
||||||
|
|
||||||
#define DECORRELATE(left, right)\
|
#define DECORRELATE(left, right)\
|
||||||
for (i = 0; i < s->blocksize; i++) {\
|
for (i = 0; i < s->blocksize; i++) {\
|
||||||
int a = s->decoded[0][i];\
|
int32_t a = s->decoded[0][i];\
|
||||||
int b = s->decoded[1][i];\
|
int32_t b = s->decoded[1][i];\
|
||||||
s->decoded[0][i] = (left) << scale;\
|
s->decoded[0][i] = (left) << scale;\
|
||||||
s->decoded[1][i] = (right) << scale;\
|
s->decoded[1][i] = (right) << scale;\
|
||||||
}\
|
}\
|
||||||
|
@ -524,7 +602,12 @@ int flac_decode_frame(FLACContext *s,
|
||||||
switch(s->decorrelation)
|
switch(s->decorrelation)
|
||||||
{
|
{
|
||||||
case INDEPENDENT:
|
case INDEPENDENT:
|
||||||
DECORRELATE(a, b) /* Always decorrelate exactly the two supported channels. */
|
if (s->channels <= 2) {
|
||||||
|
DECORRELATE(a, b) /* Always decorrelate exactly the two supported channels. */
|
||||||
|
} else {
|
||||||
|
if ((tmp=flac_downmix(s)) != 0)
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LEFT_SIDE:
|
case LEFT_SIDE:
|
||||||
DECORRELATE(a, a-b)
|
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\\
|
& Linear PCM 8/16/24/32 bit, IEEE float 32/64 bit, ITU-T G.711 a-law/$\mu$-law\\
|
||||||
Free Lossless Audio
|
Free Lossless Audio
|
||||||
& \fname{.flac}
|
& \fname{.flac}
|
||||||
& Supports multichannel tracks w/o downmixing (only left/right is played).\\
|
& Supports multichannel playback including downmixing to stereo.\\
|
||||||
Apple Lossless
|
Apple Lossless
|
||||||
& \fname{.m4a}, \fname{.mp4}
|
& \fname{.m4a}, \fname{.mp4}
|
||||||
& \\
|
& \\
|
||||||
|
@ -198,6 +198,9 @@
|
||||||
& \fname{.wv}
|
& \fname{.wv}
|
||||||
& \\
|
& \\
|
||||||
\end{rbtabular}
|
\end{rbtabular}
|
||||||
|
|
||||||
|
\note{Free Lossless Audio multichannel tracks may not play in realtime on all devices due to CPU
|
||||||
|
performance requirements.}
|
||||||
|
|
||||||
\subsection{Other Codecs}
|
\subsection{Other Codecs}
|
||||||
\begin{rbtabular}{\textwidth}{l>{\raggedright}p{6em}X}%
|
\begin{rbtabular}{\textwidth}{l>{\raggedright}p{6em}X}%
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue