summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndree Buschmann <AndreeBuschmann@t-online.de>2011-12-14 18:02:57 +0000
committerAndree Buschmann <AndreeBuschmann@t-online.de>2011-12-14 18:02:57 +0000
commit5b8ed62922fce346dc1c92db264e7ceff8c4796e (patch)
tree6965b1d3cc0f557e8574822c371d0cfe1ce6ed9c
parent6b450190774accae3bd4185b9c4329acf57b3db9 (diff)
downloadrockbox-5b8ed62922fce346dc1c92db264e7ceff8c4796e.tar.gz
rockbox-5b8ed62922fce346dc1c92db264e7ceff8c4796e.zip
FS#12443: Implement downmixing to stereo for multichannel flac.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31253 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/flac.c5
-rw-r--r--apps/codecs/libffmpegFLAC/decoder.c93
-rw-r--r--manual/appendix/file_formats.tex5
3 files changed, 94 insertions, 9 deletions
diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c
index 72bb26663a..b9f6654f92 100644
--- a/apps/codecs/flac.c
+++ b/apps/codecs/flac.c
@@ -27,7 +27,7 @@ CODEC_HEADER
27/* The output buffers containing the decoded samples (channels 0 and 1) */ 27/* The output buffers containing the decoded samples (channels 0 and 1) */
28static int32_t decoded0[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_DECODED0; 28static int32_t decoded0[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_DECODED0;
29static int32_t decoded1[MAX_BLOCKSIZE] IBSS_ATTR; 29static int32_t decoded1[MAX_BLOCKSIZE] IBSS_ATTR;
30static int32_t dummydec[MAX_BLOCKSIZE]; 30static int32_t dummydec[4][MAX_BLOCKSIZE];
31 31
32#define MAX_SUPPORTED_SEEKTABLE_SIZE 5000 32#define MAX_SUPPORTED_SEEKTABLE_SIZE 5000
33 33
@@ -98,8 +98,7 @@ static bool flac_init(FLACContext* fc, int first_frame_offset)
98 fc->decoded[1] = decoded1; 98 fc->decoded[1] = decoded1;
99 for (ch=2; ch<MAX_CHANNELS; ++ch) 99 for (ch=2; ch<MAX_CHANNELS; ++ch)
100 { 100 {
101 /* Only channel 0 and 1 are used, the other are decoded to scratch */ 101 fc->decoded[ch] = dummydec[ch-2];
102 fc->decoded[ch] = dummydec;
103 } 102 }
104 103
105 /* Skip any foreign tags at start of file */ 104 /* Skip any foreign tags at start of file */
diff --git a/apps/codecs/libffmpegFLAC/decoder.c b/apps/codecs/libffmpegFLAC/decoder.c
index ec96307383..1be5fbb6ef 100644
--- a/apps/codecs/libffmpegFLAC/decoder.c
+++ b/apps/codecs/libffmpegFLAC/decoder.c
@@ -488,9 +488,87 @@ static int decode_frame(FLACContext *s,
488 return 0; 488 return 0;
489} 489}
490 490
491static int flac_downmix(FLACContext *s)
492{
493 int32_t *FL, *FR, *FC, *SB, *RL, *RR;
494 int32_t *outL = s->decoded[0];
495 int32_t *outR = s->decoded[1];
496 int i, scale=FLAC_OUTPUT_DEPTH-s->bps;
497
498 switch(s->channels)
499 {
500 case 3: /* 3.0 channel order: FL FR FC */
501 FL = s->decoded[0];
502 FR = s->decoded[1];
503 FC = s->decoded[2];
504 /* LF = 0.66 LF + 0.33 FC
505 LR = 0.66 LR + 0.33 FC */
506 for (i=0; i<s->blocksize; ++i) {
507 int32_t a = *(FL)*2 + *(FC);
508 int32_t b = *(FR)*2 + *(FC);
509 *outL++ = ((a + (a<<2))>>4) << scale; /* 1/3 ~= 5>>4 */
510 *outR++ = ((b + (b<<2))>>4) << scale; /* 1/3 ~= 5>>4 */
511 FL++; FR++; FC++;
512 }
513 break;
514 case 4: /* 4.0 channel order: FL FR RL RR */
515 FL = s->decoded[0];
516 FR = s->decoded[1];
517 RL = s->decoded[2];
518 RR = s->decoded[3];
519 /* LF = 0.50 LF + 0.50 RL + 0.00 RR
520 LR = 0.50 LR + 0.00 RL + 0.50 RR */
521 for (i=0; i<s->blocksize; ++i) {
522 int32_t a = *(FL) + *(RL);
523 int32_t b = *(FR) + *(RR);
524 *outL++ = (a>>1) << scale;
525 *outR++ = (b>>1) << scale;
526 FL++; FR++; RL++; RR++;
527 }
528 break;
529 case 5: /* 5.0 channel order: FL FR FC RL RR */
530 FL = s->decoded[0];
531 FR = s->decoded[1];
532 FC = s->decoded[2];
533 RL = s->decoded[3];
534 RR = s->decoded[4];
535 /* LF = 0.40 LF + 0.20 FC + 0.40 RL + 0.00 RR
536 LR = 0.40 LR + 0.20 FC + 0.00 RL + 0.40 RR */
537 for (i=0; i<s->blocksize; ++i) {
538 int32_t a = *(FL)*2 + *(FC) + *(RL)*2;
539 int32_t b = *(FR)*2 + *(FC) + *(RR)*2;
540 *outL++ = ((a + (a<<1))>>4) << scale; /* 3>>4 ~= 1/5 */
541 *outR++ = ((b + (b<<1))>>4) << scale; /* 3>>4 ~= 1/5 */
542 FL++; FR++; FC++; RL++; RR++;
543 }
544 break;
545 case 6: /* 5.1 channel order: FL FR FC SUB RL RR */
546 FL = s->decoded[0];
547 FR = s->decoded[1];
548 FC = s->decoded[2];
549 SB = s->decoded[3];
550 RL = s->decoded[4];
551 RR = s->decoded[5];
552 /* LF = 0.33 LF + 0.16 SUB + 0.16 FC + 0.33 RL + 0.00 RR
553 LR = 0.33 LR + 0.16 SUB + 0.16 FC + 0.00 RL + 0.33 RR */
554 for (i=0; i<s->blocksize; ++i) {
555 int32_t a = *(FL)*2 + *(SB) + *(FC) + *(RL)*2;
556 int32_t b = *(FR)*2 + *(SB) + *(FC) + *(RR)*2;
557 *outL++ = ((a + (a<<2))>>5) << scale; /* 5>>5 ~= 1/6 */
558 *outR++ = ((b + (b<<2))>>5) << scale; /* 5>>5 ~= 1/6 */
559 FL++; FR++; SB++; FC++; RL++; RR++;
560 }
561 break;
562 default: /* 1.0 and 2.0 do not need downmix, other formats unknown. */
563 return -501;
564 break;
565 }
566 return 0;
567}
568
491int flac_decode_frame(FLACContext *s, 569int flac_decode_frame(FLACContext *s,
492 uint8_t *buf, int buf_size, 570 uint8_t *buf, int buf_size,
493 void (*yield)(void)) 571 void (*yield)(void))
494{ 572{
495 int tmp; 573 int tmp;
496 int i; 574 int i;
@@ -514,8 +592,8 @@ int flac_decode_frame(FLACContext *s,
514 592
515#define DECORRELATE(left, right)\ 593#define DECORRELATE(left, right)\
516 for (i = 0; i < s->blocksize; i++) {\ 594 for (i = 0; i < s->blocksize; i++) {\
517 int a = s->decoded[0][i];\ 595 int32_t a = s->decoded[0][i];\
518 int b = s->decoded[1][i];\ 596 int32_t b = s->decoded[1][i];\
519 s->decoded[0][i] = (left) << scale;\ 597 s->decoded[0][i] = (left) << scale;\
520 s->decoded[1][i] = (right) << scale;\ 598 s->decoded[1][i] = (right) << scale;\
521 }\ 599 }\
@@ -524,7 +602,12 @@ int flac_decode_frame(FLACContext *s,
524 switch(s->decorrelation) 602 switch(s->decorrelation)
525 { 603 {
526 case INDEPENDENT: 604 case INDEPENDENT:
527 DECORRELATE(a, b) /* Always decorrelate exactly the two supported channels. */ 605 if (s->channels <= 2) {
606 DECORRELATE(a, b) /* Always decorrelate exactly the two supported channels. */
607 } else {
608 if ((tmp=flac_downmix(s)) != 0)
609 return tmp;
610 }
528 break; 611 break;
529 case LEFT_SIDE: 612 case LEFT_SIDE:
530 DECORRELATE(a, a-b) 613 DECORRELATE(a, a-b)
diff --git a/manual/appendix/file_formats.tex b/manual/appendix/file_formats.tex
index f9f2e0a020..a086c5d2f7 100644
--- a/manual/appendix/file_formats.tex
+++ b/manual/appendix/file_formats.tex
@@ -176,7 +176,7 @@
176 & Linear PCM 8/16/24/32 bit, IEEE float 32/64 bit, ITU-T G.711 a-law/$\mu$-law\\ 176 & Linear PCM 8/16/24/32 bit, IEEE float 32/64 bit, ITU-T G.711 a-law/$\mu$-law\\
177 Free Lossless Audio 177 Free Lossless Audio
178 & \fname{.flac} 178 & \fname{.flac}
179 & Supports multichannel tracks w/o downmixing (only left/right is played).\\ 179 & Supports multichannel playback including downmixing to stereo.\\
180 Apple Lossless 180 Apple Lossless
181 & \fname{.m4a}, \fname{.mp4} 181 & \fname{.m4a}, \fname{.mp4}
182 & \\ 182 & \\
@@ -198,6 +198,9 @@
198 & \fname{.wv} 198 & \fname{.wv}
199 & \\ 199 & \\
200 \end{rbtabular} 200 \end{rbtabular}
201
202 \note{Free Lossless Audio multichannel tracks may not play in realtime on all devices due to CPU
203 performance requirements.}
201 204
202 \subsection{Other Codecs} 205 \subsection{Other Codecs}
203 \begin{rbtabular}{\textwidth}{l>{\raggedright}p{6em}X}% 206 \begin{rbtabular}{\textwidth}{l>{\raggedright}p{6em}X}%