From 8267ce8bbc57df78bdcd475f8d72649f641f1671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 18 Jan 2004 03:04:27 +0000 Subject: [PATCH] Added the MusePack (MPC) engine to our repository - it's the one use in the WinAMP plugin and is licensed under the LGPL. I've already ported it to BeOS, so it does compile without warnings. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6124 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../media/plugins/musepack/mpc/Jamfile | 14 + .../media/plugins/musepack/mpc/bitstream.cpp | 166 +++ .../media/plugins/musepack/mpc/bitstream.h | 6 + .../media/plugins/musepack/mpc/huffsv46.cpp | 230 +++ .../media/plugins/musepack/mpc/huffsv46.h | 6 + .../media/plugins/musepack/mpc/huffsv7.cpp | 462 ++++++ .../media/plugins/musepack/mpc/huffsv7.h | 6 + .../media/plugins/musepack/mpc/idtag.cpp | 887 ++++++++++++ .../media/plugins/musepack/mpc/idtag.h | 110 ++ .../media/plugins/musepack/mpc/in_mpc.cpp | 207 +++ .../media/plugins/musepack/mpc/in_mpc.h | 111 ++ .../media/plugins/musepack/mpc/minimax.h | 45 + .../media/plugins/musepack/mpc/mpc_dec.cpp | 1259 +++++++++++++++++ .../media/plugins/musepack/mpc/mpc_dec.h | 238 ++++ .../media/plugins/musepack/mpc/requant.cpp | 82 ++ .../media/plugins/musepack/mpc/requant.h | 14 + .../plugins/musepack/mpc/synth_filter.cpp | 531 +++++++ .../media/plugins/musepack/mpc/synth_filter.h | 14 + 18 files changed, 4388 insertions(+) create mode 100644 src/add-ons/media/plugins/musepack/mpc/Jamfile create mode 100644 src/add-ons/media/plugins/musepack/mpc/bitstream.cpp create mode 100644 src/add-ons/media/plugins/musepack/mpc/bitstream.h create mode 100644 src/add-ons/media/plugins/musepack/mpc/huffsv46.cpp create mode 100644 src/add-ons/media/plugins/musepack/mpc/huffsv46.h create mode 100644 src/add-ons/media/plugins/musepack/mpc/huffsv7.cpp create mode 100644 src/add-ons/media/plugins/musepack/mpc/huffsv7.h create mode 100644 src/add-ons/media/plugins/musepack/mpc/idtag.cpp create mode 100644 src/add-ons/media/plugins/musepack/mpc/idtag.h create mode 100644 src/add-ons/media/plugins/musepack/mpc/in_mpc.cpp create mode 100644 src/add-ons/media/plugins/musepack/mpc/in_mpc.h create mode 100644 src/add-ons/media/plugins/musepack/mpc/minimax.h create mode 100644 src/add-ons/media/plugins/musepack/mpc/mpc_dec.cpp create mode 100644 src/add-ons/media/plugins/musepack/mpc/mpc_dec.h create mode 100644 src/add-ons/media/plugins/musepack/mpc/requant.cpp create mode 100644 src/add-ons/media/plugins/musepack/mpc/requant.h create mode 100644 src/add-ons/media/plugins/musepack/mpc/synth_filter.cpp create mode 100644 src/add-ons/media/plugins/musepack/mpc/synth_filter.h diff --git a/src/add-ons/media/plugins/musepack/mpc/Jamfile b/src/add-ons/media/plugins/musepack/mpc/Jamfile new file mode 100644 index 0000000000..a481c4a43f --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/Jamfile @@ -0,0 +1,14 @@ +SubDir OBOS_TOP src add-ons media plugins musepack mpc ; + +StaticLibrary musepack : + bitstream.cpp + huffsv46.cpp + huffsv7.cpp + idtag.cpp + in_mpc.cpp + mpc_dec.cpp + requant.cpp + synth_filter.cpp + ; + +LinkSharedOSLibs musepack : be libmedia.so ; diff --git a/src/add-ons/media/plugins/musepack/mpc/bitstream.cpp b/src/add-ons/media/plugins/musepack/mpc/bitstream.cpp new file mode 100644 index 0000000000..9ef72405ce --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/bitstream.cpp @@ -0,0 +1,166 @@ +#include +#include "bitstream.h" + +/* C O N S T A N T S */ +const unsigned int mask [33] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, + 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, + 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, + 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, + 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, + 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, + 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, + 0xFFFFFFFF +}; + +/* F U N C T I O N S */ + +// resets bitstream decoding +void +MPC_decoder::Reset_BitstreamDecode ( void ) +{ + dword = 0; + pos = 0; + Zaehler = 0; + WordsRead = 0; +} + +// reports the number of read bits +unsigned int +MPC_decoder::BitsRead ( void ) +{ + return 32*WordsRead + pos; +} + +// read desired number of bits out of the bitstream +unsigned int +MPC_decoder::Bitstream_read ( const unsigned int bits ) +{ + unsigned int out = dword; + + pos += bits; + + if (pos<32) + { + out >>= (32-pos); + } + else + { + dword = Speicher[Zaehler=(Zaehler+1)&MEMMASK]; + pos -= 32; + if (pos) + { + out <<= pos; + out |= dword >> (32-pos); + } + ++WordsRead; + } + + return out & mask[bits]; +} + +// decode huffman +int +MPC_decoder::Huffman_Decode ( const HuffmanTyp* Table ) +{ + // load preview and decode + unsigned int code = dword << pos; + if (pos>18) code |= Speicher[(Zaehler+1)&MEMMASK] >> (32-pos); + while (code < Table->Code) Table++; + + // set the new position within bitstream without performing a dummy-read + if ((pos += Table->Length)>=32) + { + pos -= 32; + dword = Speicher[Zaehler=(Zaehler+1)&MEMMASK]; + ++WordsRead; + } + + return Table->Value; +} + +// faster huffman through previewing less bits +int +MPC_decoder::Huffman_Decode_fast ( const HuffmanTyp* Table ) +{ + // load preview and decode + unsigned int code = dword << pos; + if (pos>22) code |= Speicher[(Zaehler+1)&MEMMASK] >> (32-pos); + while (code < Table->Code) Table++; + + // set the new position within bitstream without performing a dummy-read + if ((pos += Table->Length)>=32) + { + pos -= 32; + dword = Speicher[Zaehler=(Zaehler+1)&MEMMASK]; + ++WordsRead; + } + + return Table->Value; +} + +// even faster huffman through previewing even less bits +int +MPC_decoder::Huffman_Decode_faster ( const HuffmanTyp* Table ) +{ + // load preview and decode + unsigned int code = dword << pos; + if (pos>27) code |= Speicher[(Zaehler+1)&MEMMASK] >> (32-pos); + while (code < Table->Code) Table++; + + // set the new position within bitstream without performing a dummy-read + if ((pos += Table->Length)>=32) + { + pos -= 32; + dword = Speicher[Zaehler=(Zaehler+1)&MEMMASK]; + ++WordsRead; + } + + return Table->Value; +} + +// decode SCFI-bundle (sv4,5,6) +void +MPC_decoder::SCFI_Bundle_read ( const HuffmanTyp* Table, int* SCFI, int* DSCF ) +{ + // load preview and decode + unsigned int code = dword << pos; + if (pos>26) code |= Speicher[(Zaehler+1)&MEMMASK] >> (32-pos); + while (code < Table->Code) Table++; + + // set the new position within bitstream without performing a dummy-read + if ((pos += Table->Length)>=32) + { + pos -= 32; + dword = Speicher[Zaehler=(Zaehler+1)&MEMMASK]; + ++WordsRead; + } + + *SCFI = Table->Value >> 1; + *DSCF = Table->Value & 1; +} + +static int +cmpfn ( const void* p1, const void* p2 ) +{ + if ( ((const MPC_decoder::HuffmanTyp*) p1)->Code < ((const MPC_decoder::HuffmanTyp*) p2)->Code ) return +1; + if ( ((const MPC_decoder::HuffmanTyp*) p1)->Code > ((const MPC_decoder::HuffmanTyp*) p2)->Code ) return -1; + return 0; +} + +// sort huffman-tables by codeword +// offset resulting value +void +MPC_decoder::Resort_HuffTables ( const unsigned int elements, HuffmanTyp* Table, const int offset ) +{ + unsigned int i; + + for ( i = 0; i < elements; i++ ) { + Table[i].Code <<= 32 - Table[i].Length; + Table[i].Value = i - offset; + } + qsort ( Table, elements, sizeof(*Table), cmpfn ); +} + +/* end of bitstream.c */ diff --git a/src/add-ons/media/plugins/musepack/mpc/bitstream.h b/src/add-ons/media/plugins/musepack/mpc/bitstream.h new file mode 100644 index 0000000000..9d46b449cb --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/bitstream.h @@ -0,0 +1,6 @@ +#ifndef _bitstream_decode_h_ +#define _bitstream_decode_h_ + +#include "mpc_dec.h" + +#endif diff --git a/src/add-ons/media/plugins/musepack/mpc/huffsv46.cpp b/src/add-ons/media/plugins/musepack/mpc/huffsv46.cpp new file mode 100644 index 0000000000..48035a9d48 --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/huffsv46.cpp @@ -0,0 +1,230 @@ +#include +#include "huffsv46.h" +#include "requant.h" + +void +MPC_decoder::Huffman_SV6_Decoder ( void ) +{ + Huffman_SV6_Encoder (); + Resort_HuffTables( 16, Region_A , 0); + Resort_HuffTables( 8, Region_B , 0); + Resort_HuffTables( 4, Region_C , 0); + Resort_HuffTables( 8, SCFI_Bundle , 0); + Resort_HuffTables( 13, DSCF_Entropie , 6); + Resort_HuffTables( 3, Entropie_1 , Dc[1]); + Resort_HuffTables( 5, Entropie_2 , Dc[2]); + Resort_HuffTables( 7, Entropie_3 , Dc[3]); + Resort_HuffTables( 9, Entropie_4 , Dc[4]); + Resort_HuffTables( 15, Entropie_5 , Dc[5]); + Resort_HuffTables( 31, Entropie_6 , Dc[6]); + Resort_HuffTables( 63, Entropie_7 , Dc[7]); +} + +void MPC_decoder::Huffman_SV6_Encoder ( void ) +{ + // SCFI-bundle + SCFI_Bundle[7].Code= 1; SCFI_Bundle[7].Length= 1; + SCFI_Bundle[3].Code= 1; SCFI_Bundle[3].Length= 2; + SCFI_Bundle[5].Code= 0; SCFI_Bundle[5].Length= 3; + SCFI_Bundle[1].Code= 7; SCFI_Bundle[1].Length= 5; + SCFI_Bundle[2].Code= 6; SCFI_Bundle[2].Length= 5; + SCFI_Bundle[4].Code= 4; SCFI_Bundle[4].Length= 5; + SCFI_Bundle[0].Code= 11; SCFI_Bundle[0].Length= 6; + SCFI_Bundle[6].Code= 10; SCFI_Bundle[6].Length= 6; + + // region A (subbands 0..10) + Region_A[ 1].Code= 1; Region_A[ 1].Length= 1; + Region_A[ 2].Code= 0; Region_A[ 2].Length= 2; + Region_A[ 0].Code= 2; Region_A[ 0].Length= 3; + Region_A[ 3].Code= 15; Region_A[ 3].Length= 5; + Region_A[ 5].Code= 13; Region_A[ 5].Length= 5; + Region_A[ 6].Code= 12; Region_A[ 6].Length= 5; + Region_A[ 4].Code= 29; Region_A[ 4].Length= 6; + Region_A[ 7].Code= 57; Region_A[ 7].Length= 7; + Region_A[ 8].Code= 113; Region_A[ 8].Length= 8; + Region_A[ 9].Code= 225; Region_A[ 9].Length= 9; + Region_A[10].Code= 449; Region_A[10].Length= 10; + Region_A[11].Code= 897; Region_A[11].Length= 11; + Region_A[12].Code= 1793; Region_A[12].Length= 12; + Region_A[13].Code= 3585; Region_A[13].Length= 13; + Region_A[14].Code= 7169; Region_A[14].Length= 14; + Region_A[15].Code= 7168; Region_A[15].Length= 14; + + // region B (subbands 11..22) + Region_B[1].Code= 1; Region_B[1].Length= 1; + Region_B[0].Code= 1; Region_B[0].Length= 2; + Region_B[2].Code= 1; Region_B[2].Length= 3; + Region_B[3].Code= 1; Region_B[3].Length= 4; + Region_B[4].Code= 1; Region_B[4].Length= 5; + Region_B[5].Code= 1; Region_B[5].Length= 6; + Region_B[6].Code= 1; Region_B[6].Length= 7; + Region_B[7].Code= 0; Region_B[7].Length= 7; + + // region C (subbands 23..31) + Region_C[0].Code= 1; Region_C[0].Length= 1; + Region_C[1].Code= 1; Region_C[1].Length= 2; + Region_C[2].Code= 1; Region_C[2].Length= 3; + Region_C[3].Code= 0; Region_C[3].Length= 3; + + // DSCF + DSCF_Entropie[ 6].Code= 0; DSCF_Entropie[ 6].Length= 2; + DSCF_Entropie[ 7].Code= 7; DSCF_Entropie[ 7].Length= 3; + DSCF_Entropie[ 5].Code= 4; DSCF_Entropie[ 5].Length= 3; + DSCF_Entropie[ 8].Code= 3; DSCF_Entropie[ 8].Length= 3; + DSCF_Entropie[ 9].Code= 13; DSCF_Entropie[ 9].Length= 4; + DSCF_Entropie[ 4].Code= 11; DSCF_Entropie[ 4].Length= 4; + DSCF_Entropie[10].Code= 10; DSCF_Entropie[10].Length= 4; + DSCF_Entropie[ 2].Code= 4; DSCF_Entropie[ 2].Length= 4; + DSCF_Entropie[11].Code= 25; DSCF_Entropie[11].Length= 5; + DSCF_Entropie[ 3].Code= 24; DSCF_Entropie[ 3].Length= 5; + DSCF_Entropie[ 1].Code= 11; DSCF_Entropie[ 1].Length= 5; + DSCF_Entropie[12].Code= 21; DSCF_Entropie[12].Length= 6; + DSCF_Entropie[ 0].Code= 20; DSCF_Entropie[ 0].Length= 6; + + // first quantizer + Entropie_1[1].Code= 1; Entropie_1[1].Length= 1; + Entropie_1[0].Code= 1; Entropie_1[0].Length= 2; + Entropie_1[2].Code= 0; Entropie_1[2].Length= 2; + + // second quantizer + Entropie_2[2].Code= 3; Entropie_2[2].Length= 2; + Entropie_2[3].Code= 1; Entropie_2[3].Length= 2; + Entropie_2[1].Code= 0; Entropie_2[1].Length= 2; + Entropie_2[4].Code= 5; Entropie_2[4].Length= 3; + Entropie_2[0].Code= 4; Entropie_2[0].Length= 3; + + // third quantizer + Entropie_3[3].Code= 3; Entropie_3[3].Length= 2; + Entropie_3[2].Code= 1; Entropie_3[2].Length= 2; + Entropie_3[4].Code= 0; Entropie_3[4].Length= 2; + Entropie_3[1].Code= 5; Entropie_3[1].Length= 3; + Entropie_3[5].Code= 9; Entropie_3[5].Length= 4; + Entropie_3[0].Code= 17; Entropie_3[0].Length= 5; + Entropie_3[6].Code= 16; Entropie_3[6].Length= 5; + + // forth quantizer + Entropie_4[4].Code= 0; Entropie_4[4].Length= 2; + Entropie_4[5].Code= 6; Entropie_4[5].Length= 3; + Entropie_4[3].Code= 5; Entropie_4[3].Length= 3; + Entropie_4[6].Code= 4; Entropie_4[6].Length= 3; + Entropie_4[2].Code= 3; Entropie_4[2].Length= 3; + Entropie_4[7].Code= 15; Entropie_4[7].Length= 4; + Entropie_4[1].Code= 14; Entropie_4[1].Length= 4; + Entropie_4[0].Code= 5; Entropie_4[0].Length= 4; + Entropie_4[8].Code= 4; Entropie_4[8].Length= 4; + + // fifth quantizer + Entropie_5[7 ].Code= 4; Entropie_5[7 ].Length= 3; + Entropie_5[8 ].Code= 3; Entropie_5[8 ].Length= 3; + Entropie_5[6 ].Code= 2; Entropie_5[6 ].Length= 3; + Entropie_5[9 ].Code= 0; Entropie_5[9 ].Length= 3; + Entropie_5[5 ].Code= 15; Entropie_5[5 ].Length= 4; + Entropie_5[4 ].Code= 13; Entropie_5[4 ].Length= 4; + Entropie_5[10].Code= 12; Entropie_5[10].Length= 4; + Entropie_5[11].Code= 10; Entropie_5[11].Length= 4; + Entropie_5[3 ].Code= 3; Entropie_5[3 ].Length= 4; + Entropie_5[12].Code= 2; Entropie_5[12].Length= 4; + Entropie_5[2 ].Code= 29; Entropie_5[2 ].Length= 5; + Entropie_5[1 ].Code= 23; Entropie_5[1 ].Length= 5; + Entropie_5[13].Code= 22; Entropie_5[13].Length= 5; + Entropie_5[0 ].Code= 57; Entropie_5[0 ].Length= 6; + Entropie_5[14].Code= 56; Entropie_5[14].Length= 6; + + // sixth quantizer + Entropie_6[15].Code= 9; Entropie_6[15].Length= 4; + Entropie_6[16].Code= 8; Entropie_6[16].Length= 4; + Entropie_6[14].Code= 7; Entropie_6[14].Length= 4; + Entropie_6[18].Code= 6; Entropie_6[18].Length= 4; + Entropie_6[17].Code= 5; Entropie_6[17].Length= 4; + Entropie_6[12].Code= 3; Entropie_6[12].Length= 4; + Entropie_6[13].Code= 2; Entropie_6[13].Length= 4; + Entropie_6[19].Code= 0; Entropie_6[19].Length= 4; + Entropie_6[11].Code= 31; Entropie_6[11].Length= 5; + Entropie_6[20].Code= 30; Entropie_6[20].Length= 5; + Entropie_6[10].Code= 29; Entropie_6[10].Length= 5; + Entropie_6[9 ].Code= 27; Entropie_6[9 ].Length= 5; + Entropie_6[21].Code= 26; Entropie_6[21].Length= 5; + Entropie_6[22].Code= 25; Entropie_6[22].Length= 5; + Entropie_6[8 ].Code= 24; Entropie_6[8 ].Length= 5; + Entropie_6[7 ].Code= 23; Entropie_6[7 ].Length= 5; + Entropie_6[23].Code= 21; Entropie_6[23].Length= 5; + Entropie_6[6 ].Code= 9; Entropie_6[6 ].Length= 5; + Entropie_6[24].Code= 3; Entropie_6[24].Length= 5; + Entropie_6[25].Code= 57; Entropie_6[25].Length= 6; + Entropie_6[5 ].Code= 56; Entropie_6[5 ].Length= 6; + Entropie_6[4 ].Code= 45; Entropie_6[4 ].Length= 6; + Entropie_6[26].Code= 41; Entropie_6[26].Length= 6; + Entropie_6[2 ].Code= 40; Entropie_6[2 ].Length= 6; + Entropie_6[27].Code= 17; Entropie_6[27].Length= 6; + Entropie_6[28].Code= 16; Entropie_6[28].Length= 6; + Entropie_6[3 ].Code= 5; Entropie_6[3 ].Length= 6; + Entropie_6[29].Code= 89; Entropie_6[29].Length= 7; + Entropie_6[1 ].Code= 88; Entropie_6[1 ].Length= 7; + Entropie_6[30].Code= 9; Entropie_6[30].Length= 7; + Entropie_6[0 ].Code= 8; Entropie_6[0 ].Length= 7; + + // seventh quantizer + Entropie_7[25].Code= 0; Entropie_7[25].Length= 5; + Entropie_7[37].Code= 1; Entropie_7[37].Length= 5; + Entropie_7[62].Code= 16; Entropie_7[62].Length= 8; + Entropie_7[ 0].Code= 17; Entropie_7[ 0].Length= 8; + Entropie_7[ 3].Code= 9; Entropie_7[ 3].Length= 7; + Entropie_7[ 5].Code= 10; Entropie_7[ 5].Length= 7; + Entropie_7[ 6].Code= 11; Entropie_7[ 6].Length= 7; + Entropie_7[38].Code= 3; Entropie_7[38].Length= 5; + Entropie_7[35].Code= 4; Entropie_7[35].Length= 5; + Entropie_7[33].Code= 5; Entropie_7[33].Length= 5; + Entropie_7[24].Code= 6; Entropie_7[24].Length= 5; + Entropie_7[27].Code= 7; Entropie_7[27].Length= 5; + Entropie_7[26].Code= 8; Entropie_7[26].Length= 5; + Entropie_7[12].Code= 18; Entropie_7[12].Length= 6; + Entropie_7[50].Code= 19; Entropie_7[50].Length= 6; + Entropie_7[29].Code= 10; Entropie_7[29].Length= 5; + Entropie_7[31].Code= 11; Entropie_7[31].Length= 5; + Entropie_7[36].Code= 12; Entropie_7[36].Length= 5; + Entropie_7[34].Code= 13; Entropie_7[34].Length= 5; + Entropie_7[28].Code= 14; Entropie_7[28].Length= 5; + Entropie_7[49].Code= 30; Entropie_7[49].Length= 6; + Entropie_7[56].Code= 62; Entropie_7[56].Length= 7; + Entropie_7[ 7].Code= 63; Entropie_7[ 7].Length= 7; + Entropie_7[32].Code= 16; Entropie_7[32].Length= 5; + Entropie_7[30].Code= 17; Entropie_7[30].Length= 5; + Entropie_7[13].Code= 36; Entropie_7[13].Length= 6; + Entropie_7[55].Code= 74; Entropie_7[55].Length= 7; + Entropie_7[61].Code= 150; Entropie_7[61].Length= 8; + Entropie_7[ 1].Code= 151; Entropie_7[ 1].Length= 8; + Entropie_7[14].Code= 38; Entropie_7[14].Length= 6; + Entropie_7[48].Code= 39; Entropie_7[48].Length= 6; + Entropie_7[ 4].Code= 80; Entropie_7[ 4].Length= 7; + Entropie_7[58].Code= 81; Entropie_7[58].Length= 7; + Entropie_7[47].Code= 41; Entropie_7[47].Length= 6; + Entropie_7[15].Code= 42; Entropie_7[15].Length= 6; + Entropie_7[16].Code= 43; Entropie_7[16].Length= 6; + Entropie_7[54].Code= 88; Entropie_7[54].Length= 7; + Entropie_7[ 8].Code= 89; Entropie_7[ 8].Length= 7; + Entropie_7[17].Code= 45; Entropie_7[17].Length= 6; + Entropie_7[46].Code= 46; Entropie_7[46].Length= 6; + Entropie_7[45].Code= 47; Entropie_7[45].Length= 6; + Entropie_7[53].Code= 96; Entropie_7[53].Length= 7; + Entropie_7[ 9].Code= 97; Entropie_7[ 9].Length= 7; + Entropie_7[43].Code= 49; Entropie_7[43].Length= 6; + Entropie_7[19].Code= 50; Entropie_7[19].Length= 6; + Entropie_7[18].Code= 51; Entropie_7[18].Length= 6; + Entropie_7[44].Code= 52; Entropie_7[44].Length= 6; + Entropie_7[ 2].Code= 212; Entropie_7[ 2].Length= 8; + Entropie_7[60].Code= 213; Entropie_7[60].Length= 8; + Entropie_7[10].Code= 107; Entropie_7[10].Length= 7; + Entropie_7[42].Code= 54; Entropie_7[42].Length= 6; + Entropie_7[41].Code= 55; Entropie_7[41].Length= 6; + Entropie_7[20].Code= 56; Entropie_7[20].Length= 6; + Entropie_7[21].Code= 57; Entropie_7[21].Length= 6; + Entropie_7[52].Code= 116; Entropie_7[52].Length= 7; + Entropie_7[51].Code= 117; Entropie_7[51].Length= 7; + Entropie_7[40].Code= 59; Entropie_7[40].Length= 6; + Entropie_7[22].Code= 60; Entropie_7[22].Length= 6; + Entropie_7[23].Code= 61; Entropie_7[23].Length= 6; + Entropie_7[39].Code= 62; Entropie_7[39].Length= 6; + Entropie_7[11].Code= 126; Entropie_7[11].Length= 7; + Entropie_7[57].Code= 254; Entropie_7[57].Length= 8; + Entropie_7[59].Code= 255; Entropie_7[59].Length= 8; +} diff --git a/src/add-ons/media/plugins/musepack/mpc/huffsv46.h b/src/add-ons/media/plugins/musepack/mpc/huffsv46.h new file mode 100644 index 0000000000..64b2900934 --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/huffsv46.h @@ -0,0 +1,6 @@ +#ifndef _huff_old_h_ +#define _huff_old_h_ + +#include "bitstream.h" + +#endif diff --git a/src/add-ons/media/plugins/musepack/mpc/huffsv7.cpp b/src/add-ons/media/plugins/musepack/mpc/huffsv7.cpp new file mode 100644 index 0000000000..6c7d86270a --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/huffsv7.cpp @@ -0,0 +1,462 @@ +#include "huffsv7.h" +#include "requant.h" + +void +MPC_decoder::Huffman_SV7_Decoder ( void ) +{ + Huffman_SV7_Encoder (); + Resort_HuffTables(10, &HuffHdr[0] , 5); + Resort_HuffTables( 4, &HuffSCFI[0] , 0); + Resort_HuffTables(16, &HuffDSCF[0] , 7); + Resort_HuffTables(27, &HuffQ1[0][0] , 0); + Resort_HuffTables(27, &HuffQ1[1][0] , 0); + Resort_HuffTables(25, &HuffQ2[0][0] , 0); + Resort_HuffTables(25, &HuffQ2[1][0] , 0); + Resort_HuffTables( 7, &HuffQ3[0][0] , Dc[3]); + Resort_HuffTables( 7, &HuffQ3[1][0] , Dc[3]); + Resort_HuffTables( 9, &HuffQ4[0][0] , Dc[4]); + Resort_HuffTables( 9, &HuffQ4[1][0] , Dc[4]); + Resort_HuffTables(15, &HuffQ5[0][0] , Dc[5]); + Resort_HuffTables(15, &HuffQ5[1][0] , Dc[5]); + Resort_HuffTables(31, &HuffQ6[0][0] , Dc[6]); + Resort_HuffTables(31, &HuffQ6[1][0] , Dc[6]); + Resort_HuffTables(63, &HuffQ7[0][0] , Dc[7]); + Resort_HuffTables(63, &HuffQ7[1][0] , Dc[7]); +} + +void +MPC_decoder::Huffman_SV7_Encoder ( void ) +{ + /***************************** SCFI *******************************/ + HuffSCFI[0].Code = 2; HuffSCFI[0].Length = 3; + HuffSCFI[1].Code = 1; HuffSCFI[1].Length = 1; + HuffSCFI[2].Code = 3; HuffSCFI[2].Length = 3; + HuffSCFI[3].Code = 0; HuffSCFI[3].Length = 2; + + /***************************** DSCF *******************************/ + HuffDSCF[ 0].Code = 32; HuffDSCF[ 0].Length = 6; + HuffDSCF[ 1].Code = 4; HuffDSCF[ 1].Length = 5; + HuffDSCF[ 2].Code = 17; HuffDSCF[ 2].Length = 5; + HuffDSCF[ 3].Code = 30; HuffDSCF[ 3].Length = 5; + HuffDSCF[ 4].Code = 13; HuffDSCF[ 4].Length = 4; + HuffDSCF[ 5].Code = 0; HuffDSCF[ 5].Length = 3; + HuffDSCF[ 6].Code = 3; HuffDSCF[ 6].Length = 3; + HuffDSCF[ 7].Code = 9; HuffDSCF[ 7].Length = 4; + HuffDSCF[ 8].Code = 5; HuffDSCF[ 8].Length = 3; + HuffDSCF[ 9].Code = 2; HuffDSCF[ 9].Length = 3; + HuffDSCF[10].Code = 14; HuffDSCF[10].Length = 4; + HuffDSCF[11].Code = 3; HuffDSCF[11].Length = 4; + HuffDSCF[12].Code = 31; HuffDSCF[12].Length = 5; + HuffDSCF[13].Code = 5; HuffDSCF[13].Length = 5; + HuffDSCF[14].Code = 33; HuffDSCF[14].Length = 6; + HuffDSCF[15].Code = 12; HuffDSCF[15].Length = 4; + + /************************* frame-header ***************************/ + /***************** differential quantizer indizes *****************/ + HuffHdr[0].Code = 92; HuffHdr[0].Length = 8; + HuffHdr[1].Code = 47; HuffHdr[1].Length = 7; + HuffHdr[2].Code = 10; HuffHdr[2].Length = 5; + HuffHdr[3].Code = 4; HuffHdr[3].Length = 4; + HuffHdr[4].Code = 0; HuffHdr[4].Length = 2; + HuffHdr[5].Code = 1; HuffHdr[5].Length = 1; + HuffHdr[6].Code = 3; HuffHdr[6].Length = 3; + HuffHdr[7].Code = 22; HuffHdr[7].Length = 6; + HuffHdr[8].Code = 187; HuffHdr[8].Length = 9; + HuffHdr[9].Code = 186; HuffHdr[9].Length = 9; + + /********************** 3-step quantizer **************************/ + /********************* 3 bundled samples **************************/ + //less shaped, book 0 + HuffQ1[0][ 0].Code = 54; HuffQ1[0][ 0].Length = 6; + HuffQ1[0][ 1].Code = 9; HuffQ1[0][ 1].Length = 5; + HuffQ1[0][ 2].Code = 32; HuffQ1[0][ 2].Length = 6; + HuffQ1[0][ 3].Code = 5; HuffQ1[0][ 3].Length = 5; + HuffQ1[0][ 4].Code = 10; HuffQ1[0][ 4].Length = 4; + HuffQ1[0][ 5].Code = 7; HuffQ1[0][ 5].Length = 5; + HuffQ1[0][ 6].Code = 52; HuffQ1[0][ 6].Length = 6; + HuffQ1[0][ 7].Code = 0; HuffQ1[0][ 7].Length = 5; + HuffQ1[0][ 8].Code = 35; HuffQ1[0][ 8].Length = 6; + HuffQ1[0][ 9].Code = 10; HuffQ1[0][ 9].Length = 5; + HuffQ1[0][10].Code = 6; HuffQ1[0][10].Length = 4; + HuffQ1[0][11].Code = 4; HuffQ1[0][11].Length = 5; + HuffQ1[0][12].Code = 11; HuffQ1[0][12].Length = 4; + HuffQ1[0][13].Code = 7; HuffQ1[0][13].Length = 3; + HuffQ1[0][14].Code = 12; HuffQ1[0][14].Length = 4; + HuffQ1[0][15].Code = 3; HuffQ1[0][15].Length = 5; + HuffQ1[0][16].Code = 7; HuffQ1[0][16].Length = 4; + HuffQ1[0][17].Code = 11; HuffQ1[0][17].Length = 5; + HuffQ1[0][18].Code = 34; HuffQ1[0][18].Length = 6; + HuffQ1[0][19].Code = 1; HuffQ1[0][19].Length = 5; + HuffQ1[0][20].Code = 53; HuffQ1[0][20].Length = 6; + HuffQ1[0][21].Code = 6; HuffQ1[0][21].Length = 5; + HuffQ1[0][22].Code = 9; HuffQ1[0][22].Length = 4; + HuffQ1[0][23].Code = 2; HuffQ1[0][23].Length = 5; + HuffQ1[0][24].Code = 33; HuffQ1[0][24].Length = 6; + HuffQ1[0][25].Code = 8; HuffQ1[0][25].Length = 5; + HuffQ1[0][26].Code = 55; HuffQ1[0][26].Length = 6; + + //more shaped, book 1 + HuffQ1[1][ 0].Code = 103; HuffQ1[1][ 0].Length = 8; + HuffQ1[1][ 1].Code = 62; HuffQ1[1][ 1].Length = 7; + HuffQ1[1][ 2].Code = 225; HuffQ1[1][ 2].Length = 9; + HuffQ1[1][ 3].Code = 55; HuffQ1[1][ 3].Length = 7; + HuffQ1[1][ 4].Code = 3; HuffQ1[1][ 4].Length = 4; + HuffQ1[1][ 5].Code = 52; HuffQ1[1][ 5].Length = 7; + HuffQ1[1][ 6].Code = 101; HuffQ1[1][ 6].Length = 8; + HuffQ1[1][ 7].Code = 60; HuffQ1[1][ 7].Length = 7; + HuffQ1[1][ 8].Code = 227; HuffQ1[1][ 8].Length = 9; + HuffQ1[1][ 9].Code = 24; HuffQ1[1][ 9].Length = 6; + HuffQ1[1][10].Code = 0; HuffQ1[1][10].Length = 4; + HuffQ1[1][11].Code = 61; HuffQ1[1][11].Length = 7; + HuffQ1[1][12].Code = 4; HuffQ1[1][12].Length = 4; + HuffQ1[1][13].Code = 1; HuffQ1[1][13].Length = 1; + HuffQ1[1][14].Code = 5; HuffQ1[1][14].Length = 4; + HuffQ1[1][15].Code = 63; HuffQ1[1][15].Length = 7; + HuffQ1[1][16].Code = 1; HuffQ1[1][16].Length = 4; + HuffQ1[1][17].Code = 59; HuffQ1[1][17].Length = 7; + HuffQ1[1][18].Code = 226; HuffQ1[1][18].Length = 9; + HuffQ1[1][19].Code = 57; HuffQ1[1][19].Length = 7; + HuffQ1[1][20].Code = 100; HuffQ1[1][20].Length = 8; + HuffQ1[1][21].Code = 53; HuffQ1[1][21].Length = 7; + HuffQ1[1][22].Code = 2; HuffQ1[1][22].Length = 4; + HuffQ1[1][23].Code = 54; HuffQ1[1][23].Length = 7; + HuffQ1[1][24].Code = 224; HuffQ1[1][24].Length = 9; + HuffQ1[1][25].Code = 58; HuffQ1[1][25].Length = 7; + HuffQ1[1][26].Code = 102; HuffQ1[1][26].Length = 8; + + /********************** 5-step quantizer **************************/ + /********************* 2 bundled samples **************************/ + //less shaped, book 0 + HuffQ2[0][ 0].Code = 89; HuffQ2[0][ 0].Length = 7; + HuffQ2[0][ 1].Code = 47; HuffQ2[0][ 1].Length = 6; + HuffQ2[0][ 2].Code = 15; HuffQ2[0][ 2].Length = 5; + HuffQ2[0][ 3].Code = 0; HuffQ2[0][ 3].Length = 5; + HuffQ2[0][ 4].Code = 91; HuffQ2[0][ 4].Length = 7; + HuffQ2[0][ 5].Code = 4; HuffQ2[0][ 5].Length = 5; + HuffQ2[0][ 6].Code = 6; HuffQ2[0][ 6].Length = 4; + HuffQ2[0][ 7].Code = 13; HuffQ2[0][ 7].Length = 4; + HuffQ2[0][ 8].Code = 4; HuffQ2[0][ 8].Length = 4; + HuffQ2[0][ 9].Code = 5; HuffQ2[0][ 9].Length = 5; + HuffQ2[0][10].Code = 20; HuffQ2[0][10].Length = 5; + HuffQ2[0][11].Code = 12; HuffQ2[0][11].Length = 4; + HuffQ2[0][12].Code = 4; HuffQ2[0][12].Length = 3; + HuffQ2[0][13].Code = 15; HuffQ2[0][13].Length = 4; + HuffQ2[0][14].Code = 14; HuffQ2[0][14].Length = 5; + HuffQ2[0][15].Code = 3; HuffQ2[0][15].Length = 5; + HuffQ2[0][16].Code = 3; HuffQ2[0][16].Length = 4; + HuffQ2[0][17].Code = 14; HuffQ2[0][17].Length = 4; + HuffQ2[0][18].Code = 5; HuffQ2[0][18].Length = 4; + HuffQ2[0][19].Code = 1; HuffQ2[0][19].Length = 5; + HuffQ2[0][20].Code = 90; HuffQ2[0][20].Length = 7; + HuffQ2[0][21].Code = 2; HuffQ2[0][21].Length = 5; + HuffQ2[0][22].Code = 21; HuffQ2[0][22].Length = 5; + HuffQ2[0][23].Code = 46; HuffQ2[0][23].Length = 6; + HuffQ2[0][24].Code = 88; HuffQ2[0][24].Length = 7; + + //more shaped, book 1 + HuffQ2[1][ 0].Code = 921; HuffQ2[1][ 0].Length = 10; + HuffQ2[1][ 1].Code = 113; HuffQ2[1][ 1].Length = 7; + HuffQ2[1][ 2].Code = 51; HuffQ2[1][ 2].Length = 6; + HuffQ2[1][ 3].Code = 231; HuffQ2[1][ 3].Length = 8; + HuffQ2[1][ 4].Code = 922; HuffQ2[1][ 4].Length = 10; + HuffQ2[1][ 5].Code = 104; HuffQ2[1][ 5].Length = 7; + HuffQ2[1][ 6].Code = 30; HuffQ2[1][ 6].Length = 5; + HuffQ2[1][ 7].Code = 0; HuffQ2[1][ 7].Length = 3; + HuffQ2[1][ 8].Code = 29; HuffQ2[1][ 8].Length = 5; + HuffQ2[1][ 9].Code = 105; HuffQ2[1][ 9].Length = 7; + HuffQ2[1][10].Code = 50; HuffQ2[1][10].Length = 6; + HuffQ2[1][11].Code = 1; HuffQ2[1][11].Length = 3; + HuffQ2[1][12].Code = 2; HuffQ2[1][12].Length = 2; + HuffQ2[1][13].Code = 3; HuffQ2[1][13].Length = 3; + HuffQ2[1][14].Code = 49; HuffQ2[1][14].Length = 6; + HuffQ2[1][15].Code = 107; HuffQ2[1][15].Length = 7; + HuffQ2[1][16].Code = 27; HuffQ2[1][16].Length = 5; + HuffQ2[1][17].Code = 2; HuffQ2[1][17].Length = 3; + HuffQ2[1][18].Code = 31; HuffQ2[1][18].Length = 5; + HuffQ2[1][19].Code = 112; HuffQ2[1][19].Length = 7; + HuffQ2[1][20].Code = 920; HuffQ2[1][20].Length = 10; + HuffQ2[1][21].Code = 106; HuffQ2[1][21].Length = 7; + HuffQ2[1][22].Code = 48; HuffQ2[1][22].Length = 6; + HuffQ2[1][23].Code = 114; HuffQ2[1][23].Length = 7; + HuffQ2[1][24].Code = 923; HuffQ2[1][24].Length = 10; + + /********************** 7-step quantizer **************************/ + /*********************** single samples ***************************/ + //less shaped, book 0 + HuffQ3[0][0].Code = 12; HuffQ3[0][0].Length = 4; + HuffQ3[0][1].Code = 4; HuffQ3[0][1].Length = 3; + HuffQ3[0][2].Code = 0; HuffQ3[0][2].Length = 2; + HuffQ3[0][3].Code = 1; HuffQ3[0][3].Length = 2; + HuffQ3[0][4].Code = 7; HuffQ3[0][4].Length = 3; + HuffQ3[0][5].Code = 5; HuffQ3[0][5].Length = 3; + HuffQ3[0][6].Code = 13; HuffQ3[0][6].Length = 4; + + //more shaped, book 1 + HuffQ3[1][0].Code = 4; HuffQ3[1][0].Length = 5; + HuffQ3[1][1].Code = 3; HuffQ3[1][1].Length = 4; + HuffQ3[1][2].Code = 2; HuffQ3[1][2].Length = 2; + HuffQ3[1][3].Code = 3; HuffQ3[1][3].Length = 2; + HuffQ3[1][4].Code = 1; HuffQ3[1][4].Length = 2; + HuffQ3[1][5].Code = 0; HuffQ3[1][5].Length = 3; + HuffQ3[1][6].Code = 5; HuffQ3[1][6].Length = 5; + + /********************** 9-step quantizer **************************/ + /*********************** single samples ***************************/ + //less shaped, book 0 + HuffQ4[0][0].Code = 5; HuffQ4[0][0].Length = 4; + HuffQ4[0][1].Code = 0; HuffQ4[0][1].Length = 3; + HuffQ4[0][2].Code = 4; HuffQ4[0][2].Length = 3; + HuffQ4[0][3].Code = 6; HuffQ4[0][3].Length = 3; + HuffQ4[0][4].Code = 7; HuffQ4[0][4].Length = 3; + HuffQ4[0][5].Code = 5; HuffQ4[0][5].Length = 3; + HuffQ4[0][6].Code = 3; HuffQ4[0][6].Length = 3; + HuffQ4[0][7].Code = 1; HuffQ4[0][7].Length = 3; + HuffQ4[0][8].Code = 4; HuffQ4[0][8].Length = 4; + + //more shaped, book 1 + HuffQ4[1][0].Code = 9; HuffQ4[1][0].Length = 5; + HuffQ4[1][1].Code = 12; HuffQ4[1][1].Length = 4; + HuffQ4[1][2].Code = 3; HuffQ4[1][2].Length = 3; + HuffQ4[1][3].Code = 0; HuffQ4[1][3].Length = 2; + HuffQ4[1][4].Code = 2; HuffQ4[1][4].Length = 2; + HuffQ4[1][5].Code = 7; HuffQ4[1][5].Length = 3; + HuffQ4[1][6].Code = 13; HuffQ4[1][6].Length = 4; + HuffQ4[1][7].Code = 5; HuffQ4[1][7].Length = 4; + HuffQ4[1][8].Code = 8; HuffQ4[1][8].Length = 5; + + /********************* 15-step quantizer **************************/ + /*********************** single samples ***************************/ + //less shaped, book 0 + HuffQ5[0][ 0].Code = 57; HuffQ5[0][ 0].Length = 6; + HuffQ5[0][ 1].Code = 23; HuffQ5[0][ 1].Length = 5; + HuffQ5[0][ 2].Code = 8; HuffQ5[0][ 2].Length = 4; + HuffQ5[0][ 3].Code = 10; HuffQ5[0][ 3].Length = 4; + HuffQ5[0][ 4].Code = 13; HuffQ5[0][ 4].Length = 4; + HuffQ5[0][ 5].Code = 0; HuffQ5[0][ 5].Length = 3; + HuffQ5[0][ 6].Code = 2; HuffQ5[0][ 6].Length = 3; + HuffQ5[0][ 7].Code = 3; HuffQ5[0][ 7].Length = 3; + HuffQ5[0][ 8].Code = 1; HuffQ5[0][ 8].Length = 3; + HuffQ5[0][ 9].Code = 15; HuffQ5[0][ 9].Length = 4; + HuffQ5[0][10].Code = 12; HuffQ5[0][10].Length = 4; + HuffQ5[0][11].Code = 9; HuffQ5[0][11].Length = 4; + HuffQ5[0][12].Code = 29; HuffQ5[0][12].Length = 5; + HuffQ5[0][13].Code = 22; HuffQ5[0][13].Length = 5; + HuffQ5[0][14].Code = 56; HuffQ5[0][14].Length = 6; + + //more shaped, book 1 + HuffQ5[1][ 0].Code = 229; HuffQ5[1][ 0].Length = 8; + HuffQ5[1][ 1].Code = 56; HuffQ5[1][ 1].Length = 6; + HuffQ5[1][ 2].Code = 7; HuffQ5[1][ 2].Length = 5; + HuffQ5[1][ 3].Code = 2; HuffQ5[1][ 3].Length = 4; + HuffQ5[1][ 4].Code = 0; HuffQ5[1][ 4].Length = 3; + HuffQ5[1][ 5].Code = 3; HuffQ5[1][ 5].Length = 3; + HuffQ5[1][ 6].Code = 5; HuffQ5[1][ 6].Length = 3; + HuffQ5[1][ 7].Code = 6; HuffQ5[1][ 7].Length = 3; + HuffQ5[1][ 8].Code = 4; HuffQ5[1][ 8].Length = 3; + HuffQ5[1][ 9].Code = 2; HuffQ5[1][ 9].Length = 3; + HuffQ5[1][10].Code = 15; HuffQ5[1][10].Length = 4; + HuffQ5[1][11].Code = 29; HuffQ5[1][11].Length = 5; + HuffQ5[1][12].Code = 6; HuffQ5[1][12].Length = 5; + HuffQ5[1][13].Code = 115; HuffQ5[1][13].Length = 7; + HuffQ5[1][14].Code = 228; HuffQ5[1][14].Length = 8; + + /********************* 31-step quantizer **************************/ + /*********************** single samples ***************************/ + //less shaped, book 0 + HuffQ6[0][ 0].Code = 65; HuffQ6[0][ 0].Length = 7; + HuffQ6[0][ 1].Code = 6; HuffQ6[0][ 1].Length = 6; + HuffQ6[0][ 2].Code = 44; HuffQ6[0][ 2].Length = 6; + HuffQ6[0][ 3].Code = 45; HuffQ6[0][ 3].Length = 6; + HuffQ6[0][ 4].Code = 59; HuffQ6[0][ 4].Length = 6; + HuffQ6[0][ 5].Code = 13; HuffQ6[0][ 5].Length = 5; + HuffQ6[0][ 6].Code = 17; HuffQ6[0][ 6].Length = 5; + HuffQ6[0][ 7].Code = 19; HuffQ6[0][ 7].Length = 5; + HuffQ6[0][ 8].Code = 23; HuffQ6[0][ 8].Length = 5; + HuffQ6[0][ 9].Code = 21; HuffQ6[0][ 9].Length = 5; + HuffQ6[0][10].Code = 26; HuffQ6[0][10].Length = 5; + HuffQ6[0][11].Code = 30; HuffQ6[0][11].Length = 5; + HuffQ6[0][12].Code = 0; HuffQ6[0][12].Length = 4; + HuffQ6[0][13].Code = 2; HuffQ6[0][13].Length = 4; + HuffQ6[0][14].Code = 5; HuffQ6[0][14].Length = 4; + HuffQ6[0][15].Code = 7; HuffQ6[0][15].Length = 4; + HuffQ6[0][16].Code = 3; HuffQ6[0][16].Length = 4; + HuffQ6[0][17].Code = 4; HuffQ6[0][17].Length = 4; + HuffQ6[0][18].Code = 31; HuffQ6[0][18].Length = 5; + HuffQ6[0][19].Code = 28; HuffQ6[0][19].Length = 5; + HuffQ6[0][20].Code = 25; HuffQ6[0][20].Length = 5; + HuffQ6[0][21].Code = 27; HuffQ6[0][21].Length = 5; + HuffQ6[0][22].Code = 24; HuffQ6[0][22].Length = 5; + HuffQ6[0][23].Code = 20; HuffQ6[0][23].Length = 5; + HuffQ6[0][24].Code = 18; HuffQ6[0][24].Length = 5; + HuffQ6[0][25].Code = 12; HuffQ6[0][25].Length = 5; + HuffQ6[0][26].Code = 2; HuffQ6[0][26].Length = 5; + HuffQ6[0][27].Code = 58; HuffQ6[0][27].Length = 6; + HuffQ6[0][28].Code = 33; HuffQ6[0][28].Length = 6; + HuffQ6[0][29].Code = 7; HuffQ6[0][29].Length = 6; + HuffQ6[0][30].Code = 64; HuffQ6[0][30].Length = 7; + + //more shaped, book 1 + HuffQ6[1][ 0].Code = 6472; HuffQ6[1][ 0].Length = 13; + HuffQ6[1][ 1].Code = 6474; HuffQ6[1][ 1].Length = 13; + HuffQ6[1][ 2].Code = 808; HuffQ6[1][ 2].Length = 10; + HuffQ6[1][ 3].Code = 405; HuffQ6[1][ 3].Length = 9; + HuffQ6[1][ 4].Code = 203; HuffQ6[1][ 4].Length = 8; + HuffQ6[1][ 5].Code = 102; HuffQ6[1][ 5].Length = 7; + HuffQ6[1][ 6].Code = 49; HuffQ6[1][ 6].Length = 6; + HuffQ6[1][ 7].Code = 9; HuffQ6[1][ 7].Length = 5; + HuffQ6[1][ 8].Code = 15; HuffQ6[1][ 8].Length = 5; + HuffQ6[1][ 9].Code = 31; HuffQ6[1][ 9].Length = 5; + HuffQ6[1][10].Code = 2; HuffQ6[1][10].Length = 4; + HuffQ6[1][11].Code = 6; HuffQ6[1][11].Length = 4; + HuffQ6[1][12].Code = 8; HuffQ6[1][12].Length = 4; + HuffQ6[1][13].Code = 11; HuffQ6[1][13].Length = 4; + HuffQ6[1][14].Code = 13; HuffQ6[1][14].Length = 4; + HuffQ6[1][15].Code = 0; HuffQ6[1][15].Length = 3; + HuffQ6[1][16].Code = 14; HuffQ6[1][16].Length = 4; + HuffQ6[1][17].Code = 10; HuffQ6[1][17].Length = 4; + HuffQ6[1][18].Code = 9; HuffQ6[1][18].Length = 4; + HuffQ6[1][19].Code = 5; HuffQ6[1][19].Length = 4; + HuffQ6[1][20].Code = 3; HuffQ6[1][20].Length = 4; + HuffQ6[1][21].Code = 30; HuffQ6[1][21].Length = 5; + HuffQ6[1][22].Code = 14; HuffQ6[1][22].Length = 5; + HuffQ6[1][23].Code = 8; HuffQ6[1][23].Length = 5; + HuffQ6[1][24].Code = 48; HuffQ6[1][24].Length = 6; + HuffQ6[1][25].Code = 103; HuffQ6[1][25].Length = 7; + HuffQ6[1][26].Code = 201; HuffQ6[1][26].Length = 8; + HuffQ6[1][27].Code = 200; HuffQ6[1][27].Length = 8; + HuffQ6[1][28].Code = 1619; HuffQ6[1][28].Length = 11; + HuffQ6[1][29].Code = 6473; HuffQ6[1][29].Length = 13; + HuffQ6[1][30].Code = 6475; HuffQ6[1][30].Length = 13; + + /********************* 63-step quantizer **************************/ + /*********************** single samples ***************************/ + //less shaped, book 0 + HuffQ7[0][ 0].Code = 103; HuffQ7[0][ 0].Length = 8; /* 0.003338 - 01100111 */ + HuffQ7[0][ 1].Code = 153; HuffQ7[0][ 1].Length = 8; /* 0.003766 - 10011001 */ + HuffQ7[0][ 2].Code = 181; HuffQ7[0][ 2].Length = 8; /* 0.004715 - 10110101 */ + HuffQ7[0][ 3].Code = 233; HuffQ7[0][ 3].Length = 8; /* 0.005528 - 11101001 */ + HuffQ7[0][ 4].Code = 64; HuffQ7[0][ 4].Length = 7; /* 0.006677 - 1000000 */ + HuffQ7[0][ 5].Code = 65; HuffQ7[0][ 5].Length = 7; /* 0.007041 - 1000001 */ + HuffQ7[0][ 6].Code = 77; HuffQ7[0][ 6].Length = 7; /* 0.007733 - 1001101 */ + HuffQ7[0][ 7].Code = 81; HuffQ7[0][ 7].Length = 7; /* 0.008296 - 1010001 */ + HuffQ7[0][ 8].Code = 91; HuffQ7[0][ 8].Length = 7; /* 0.009295 - 1011011 */ + HuffQ7[0][ 9].Code = 113; HuffQ7[0][ 9].Length = 7; /* 0.010814 - 1110001 */ + HuffQ7[0][10].Code = 112; HuffQ7[0][10].Length = 7; /* 0.010807 - 1110000 */ + HuffQ7[0][11].Code = 24; HuffQ7[0][11].Length = 6; /* 0.012748 - 011000 */ + HuffQ7[0][12].Code = 29; HuffQ7[0][12].Length = 6; /* 0.013390 - 011101 */ + HuffQ7[0][13].Code = 35; HuffQ7[0][13].Length = 6; /* 0.014224 - 100011 */ + HuffQ7[0][14].Code = 37; HuffQ7[0][14].Length = 6; /* 0.015201 - 100101 */ + HuffQ7[0][15].Code = 41; HuffQ7[0][15].Length = 6; /* 0.016642 - 101001 */ + HuffQ7[0][16].Code = 44; HuffQ7[0][16].Length = 6; /* 0.017292 - 101100 */ + HuffQ7[0][17].Code = 46; HuffQ7[0][17].Length = 6; /* 0.018647 - 101110 */ + HuffQ7[0][18].Code = 51; HuffQ7[0][18].Length = 6; /* 0.020473 - 110011 */ + HuffQ7[0][19].Code = 49; HuffQ7[0][19].Length = 6; /* 0.020152 - 110001 */ + HuffQ7[0][20].Code = 54; HuffQ7[0][20].Length = 6; /* 0.021315 - 110110 */ + HuffQ7[0][21].Code = 55; HuffQ7[0][21].Length = 6; /* 0.021358 - 110111 */ + HuffQ7[0][22].Code = 57; HuffQ7[0][22].Length = 6; /* 0.021700 - 111001 */ + HuffQ7[0][23].Code = 60; HuffQ7[0][23].Length = 6; /* 0.022449 - 111100 */ + HuffQ7[0][24].Code = 0; HuffQ7[0][24].Length = 5; /* 0.023063 - 00000 */ + HuffQ7[0][25].Code = 2; HuffQ7[0][25].Length = 5; /* 0.023854 - 00010 */ + HuffQ7[0][26].Code = 10; HuffQ7[0][26].Length = 5; /* 0.025481 - 01010 */ + HuffQ7[0][27].Code = 5; HuffQ7[0][27].Length = 5; /* 0.024867 - 00101 */ + HuffQ7[0][28].Code = 9; HuffQ7[0][28].Length = 5; /* 0.025352 - 01001 */ + HuffQ7[0][29].Code = 6; HuffQ7[0][29].Length = 5; /* 0.025074 - 00110 */ + HuffQ7[0][30].Code = 13; HuffQ7[0][30].Length = 5; /* 0.025745 - 01101 */ + HuffQ7[0][31].Code = 7; HuffQ7[0][31].Length = 5; /* 0.025195 - 00111 */ + HuffQ7[0][32].Code = 11; HuffQ7[0][32].Length = 5; /* 0.025502 - 01011 */ + HuffQ7[0][33].Code = 15; HuffQ7[0][33].Length = 5; /* 0.026251 - 01111 */ + HuffQ7[0][34].Code = 8; HuffQ7[0][34].Length = 5; /* 0.025260 - 01000 */ + HuffQ7[0][35].Code = 4; HuffQ7[0][35].Length = 5; /* 0.024418 - 00100 */ + HuffQ7[0][36].Code = 3; HuffQ7[0][36].Length = 5; /* 0.023983 - 00011 */ + HuffQ7[0][37].Code = 1; HuffQ7[0][37].Length = 5; /* 0.023697 - 00001 */ + HuffQ7[0][38].Code = 63; HuffQ7[0][38].Length = 6; /* 0.023041 - 111111 */ + HuffQ7[0][39].Code = 62; HuffQ7[0][39].Length = 6; /* 0.022656 - 111110 */ + HuffQ7[0][40].Code = 61; HuffQ7[0][40].Length = 6; /* 0.022549 - 111101 */ + HuffQ7[0][41].Code = 53; HuffQ7[0][41].Length = 6; /* 0.021151 - 110101 */ + HuffQ7[0][42].Code = 59; HuffQ7[0][42].Length = 6; /* 0.022042 - 111011 */ + HuffQ7[0][43].Code = 52; HuffQ7[0][43].Length = 6; /* 0.020837 - 110100 */ + HuffQ7[0][44].Code = 48; HuffQ7[0][44].Length = 6; /* 0.019446 - 110000 */ + HuffQ7[0][45].Code = 47; HuffQ7[0][45].Length = 6; /* 0.019189 - 101111 */ + HuffQ7[0][46].Code = 43; HuffQ7[0][46].Length = 6; /* 0.017177 - 101011 */ + HuffQ7[0][47].Code = 42; HuffQ7[0][47].Length = 6; /* 0.017035 - 101010 */ + HuffQ7[0][48].Code = 39; HuffQ7[0][48].Length = 6; /* 0.015287 - 100111 */ + HuffQ7[0][49].Code = 36; HuffQ7[0][49].Length = 6; /* 0.014559 - 100100 */ + HuffQ7[0][50].Code = 33; HuffQ7[0][50].Length = 6; /* 0.014117 - 100001 */ + HuffQ7[0][51].Code = 28; HuffQ7[0][51].Length = 6; /* 0.012776 - 011100 */ + HuffQ7[0][52].Code = 117; HuffQ7[0][52].Length = 7; /* 0.011107 - 1110101 */ + HuffQ7[0][53].Code = 101; HuffQ7[0][53].Length = 7; /* 0.010636 - 1100101 */ + HuffQ7[0][54].Code = 100; HuffQ7[0][54].Length = 7; /* 0.009751 - 1100100 */ + HuffQ7[0][55].Code = 80; HuffQ7[0][55].Length = 7; /* 0.008132 - 1010000 */ + HuffQ7[0][56].Code = 69; HuffQ7[0][56].Length = 7; /* 0.007091 - 1000101 */ + HuffQ7[0][57].Code = 68; HuffQ7[0][57].Length = 7; /* 0.007084 - 1000100 */ + HuffQ7[0][58].Code = 50; HuffQ7[0][58].Length = 7; /* 0.006277 - 0110010 */ + HuffQ7[0][59].Code = 232; HuffQ7[0][59].Length = 8; /* 0.005386 - 11101000 */ + HuffQ7[0][60].Code = 180; HuffQ7[0][60].Length = 8; /* 0.004408 - 10110100 */ + HuffQ7[0][61].Code = 152; HuffQ7[0][61].Length = 8; /* 0.003759 - 10011000 */ + HuffQ7[0][62].Code = 102; HuffQ7[0][62].Length = 8; /* 0.003160 - 01100110 */ + + //more shaped, book 1 + HuffQ7[1][ 0].Code = 14244; HuffQ7[1][ 0].Length = 14; /* 0.000059 - 11011110100100 */ + HuffQ7[1][ 1].Code = 14253; HuffQ7[1][ 1].Length = 14; /* 0.000098 - 11011110101101 */ + HuffQ7[1][ 2].Code = 14246; HuffQ7[1][ 2].Length = 14; /* 0.000078 - 11011110100110 */ + HuffQ7[1][ 3].Code = 14254; HuffQ7[1][ 3].Length = 14; /* 0.000111 - 11011110101110 */ + HuffQ7[1][ 4].Code = 3562; HuffQ7[1][ 4].Length = 12; /* 0.000320 - 110111101010 */ + HuffQ7[1][ 5].Code = 752; HuffQ7[1][ 5].Length = 10; /* 0.000920 - 1011110000 */ + HuffQ7[1][ 6].Code = 753; HuffQ7[1][ 6].Length = 10; /* 0.001057 - 1011110001 */ + HuffQ7[1][ 7].Code = 160; HuffQ7[1][ 7].Length = 9; /* 0.001403 - 010100000 */ + HuffQ7[1][ 8].Code = 162; HuffQ7[1][ 8].Length = 9; /* 0.001579 - 010100010 */ + HuffQ7[1][ 9].Code = 444; HuffQ7[1][ 9].Length = 9; /* 0.002486 - 110111100 */ + HuffQ7[1][10].Code = 122; HuffQ7[1][10].Length = 8; /* 0.003772 - 01111010 */ + HuffQ7[1][11].Code = 223; HuffQ7[1][11].Length = 8; /* 0.005710 - 11011111 */ + HuffQ7[1][12].Code = 60; HuffQ7[1][12].Length = 7; /* 0.006858 - 0111100 */ + HuffQ7[1][13].Code = 73; HuffQ7[1][13].Length = 7; /* 0.008033 - 1001001 */ + HuffQ7[1][14].Code = 110; HuffQ7[1][14].Length = 7; /* 0.009827 - 1101110 */ + HuffQ7[1][15].Code = 14; HuffQ7[1][15].Length = 6; /* 0.012601 - 001110 */ + HuffQ7[1][16].Code = 24; HuffQ7[1][16].Length = 6; /* 0.013194 - 011000 */ + HuffQ7[1][17].Code = 25; HuffQ7[1][17].Length = 6; /* 0.013938 - 011001 */ + HuffQ7[1][18].Code = 34; HuffQ7[1][18].Length = 6; /* 0.015693 - 100010 */ + HuffQ7[1][19].Code = 37; HuffQ7[1][19].Length = 6; /* 0.017846 - 100101 */ + HuffQ7[1][20].Code = 54; HuffQ7[1][20].Length = 6; /* 0.020078 - 110110 */ + HuffQ7[1][21].Code = 3; HuffQ7[1][21].Length = 5; /* 0.022975 - 00011 */ + HuffQ7[1][22].Code = 9; HuffQ7[1][22].Length = 5; /* 0.025631 - 01001 */ + HuffQ7[1][23].Code = 11; HuffQ7[1][23].Length = 5; /* 0.027021 - 01011 */ + HuffQ7[1][24].Code = 16; HuffQ7[1][24].Length = 5; /* 0.031465 - 10000 */ + HuffQ7[1][25].Code = 19; HuffQ7[1][25].Length = 5; /* 0.034244 - 10011 */ + HuffQ7[1][26].Code = 21; HuffQ7[1][26].Length = 5; /* 0.035921 - 10101 */ + HuffQ7[1][27].Code = 24; HuffQ7[1][27].Length = 5; /* 0.037938 - 11000 */ + HuffQ7[1][28].Code = 26; HuffQ7[1][28].Length = 5; /* 0.039595 - 11010 */ + HuffQ7[1][29].Code = 29; HuffQ7[1][29].Length = 5; /* 0.041546 - 11101 */ + HuffQ7[1][30].Code = 31; HuffQ7[1][30].Length = 5; /* 0.042623 - 11111 */ + HuffQ7[1][31].Code = 2; HuffQ7[1][31].Length = 4; /* 0.045180 - 0010 */ + HuffQ7[1][32].Code = 0; HuffQ7[1][32].Length = 4; /* 0.043151 - 0000 */ + HuffQ7[1][33].Code = 30; HuffQ7[1][33].Length = 5; /* 0.042538 - 11110 */ + HuffQ7[1][34].Code = 28; HuffQ7[1][34].Length = 5; /* 0.041422 - 11100 */ + HuffQ7[1][35].Code = 25; HuffQ7[1][35].Length = 5; /* 0.039145 - 11001 */ + HuffQ7[1][36].Code = 22; HuffQ7[1][36].Length = 5; /* 0.036691 - 10110 */ + HuffQ7[1][37].Code = 20; HuffQ7[1][37].Length = 5; /* 0.034955 - 10100 */ + HuffQ7[1][38].Code = 14; HuffQ7[1][38].Length = 5; /* 0.029155 - 01110 */ + HuffQ7[1][39].Code = 13; HuffQ7[1][39].Length = 5; /* 0.027921 - 01101 */ + HuffQ7[1][40].Code = 8; HuffQ7[1][40].Length = 5; /* 0.025553 - 01000 */ + HuffQ7[1][41].Code = 6; HuffQ7[1][41].Length = 5; /* 0.023093 - 00110 */ + HuffQ7[1][42].Code = 2; HuffQ7[1][42].Length = 5; /* 0.021200 - 00010 */ + HuffQ7[1][43].Code = 46; HuffQ7[1][43].Length = 6; /* 0.018134 - 101110 */ + HuffQ7[1][44].Code = 35; HuffQ7[1][44].Length = 6; /* 0.015824 - 100011 */ + HuffQ7[1][45].Code = 31; HuffQ7[1][45].Length = 6; /* 0.014701 - 011111 */ + HuffQ7[1][46].Code = 21; HuffQ7[1][46].Length = 6; /* 0.013187 - 010101 */ + HuffQ7[1][47].Code = 15; HuffQ7[1][47].Length = 6; /* 0.012776 - 001111 */ + HuffQ7[1][48].Code = 95; HuffQ7[1][48].Length = 7; /* 0.009664 - 1011111 */ + HuffQ7[1][49].Code = 72; HuffQ7[1][49].Length = 7; /* 0.007922 - 1001000 */ + HuffQ7[1][50].Code = 41; HuffQ7[1][50].Length = 7; /* 0.006838 - 0101001 */ + HuffQ7[1][51].Code = 189; HuffQ7[1][51].Length = 8; /* 0.005024 - 10111101 */ + HuffQ7[1][52].Code = 123; HuffQ7[1][52].Length = 8; /* 0.003830 - 01111011 */ + HuffQ7[1][53].Code = 377; HuffQ7[1][53].Length = 9; /* 0.002232 - 101111001 */ + HuffQ7[1][54].Code = 161; HuffQ7[1][54].Length = 9; /* 0.001566 - 010100001 */ + HuffQ7[1][55].Code = 891; HuffQ7[1][55].Length = 10; /* 0.001383 - 1101111011 */ + HuffQ7[1][56].Code = 327; HuffQ7[1][56].Length = 10; /* 0.000900 - 0101000111 */ + HuffQ7[1][57].Code = 326; HuffQ7[1][57].Length = 10; /* 0.000790 - 0101000110 */ + HuffQ7[1][58].Code = 3560; HuffQ7[1][58].Length = 12; /* 0.000254 - 110111101000 */ + HuffQ7[1][59].Code = 14255; HuffQ7[1][59].Length = 14; /* 0.000117 - 11011110101111 */ + HuffQ7[1][60].Code = 14247; HuffQ7[1][60].Length = 14; /* 0.000085 - 11011110100111 */ + HuffQ7[1][61].Code = 14252; HuffQ7[1][61].Length = 14; /* 0.000085 - 11011110101100 */ + HuffQ7[1][62].Code = 14245; HuffQ7[1][62].Length = 14; /* 0.000065 - 11011110100101 */ +} diff --git a/src/add-ons/media/plugins/musepack/mpc/huffsv7.h b/src/add-ons/media/plugins/musepack/mpc/huffsv7.h new file mode 100644 index 0000000000..b7620ba5ef --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/huffsv7.h @@ -0,0 +1,6 @@ +#ifndef _huff_new_h_ +#define _huff_new_h + +#include "bitstream.h" + +#endif diff --git a/src/add-ons/media/plugins/musepack/mpc/idtag.cpp b/src/add-ons/media/plugins/musepack/mpc/idtag.cpp new file mode 100644 index 0000000000..a2d4e86bd8 --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/idtag.cpp @@ -0,0 +1,887 @@ +#include + +#include +#include +#include +#include +#include "in_mpc.h" +#include "idtag.h" +#include "mpc_dec.h" + +static const char ListSeparator[] = { "; " }; + +/* V A R I A B L E S */ +static const char* GenreList [] = { + "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", + "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", + "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", + "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", + "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", + "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", + "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", + "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", + "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", + "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", + "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", + "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", + "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", + "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", + "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", + "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", + "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", + "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", + "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", + "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", + "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall", + "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror", + "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat", + "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C", + "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", + "SynthPop", +}; + + +// free tagdata from memory +void +StreamInfo::Clear() +{ + size_t i; + + if ( tagitems != NULL ) { + for ( i = 0; i < tagitem_count; i++ ) { + if ( tagitems[i].Item ) free ( tagitems[i].Item ); + if ( tagitems[i].Value ) free ( tagitems[i].Value ); + } + + free ( tagitems ); + tagitems = NULL; + } + + if ( filename ) { + free ( filename ); + filename = NULL; + } + + tagitem_count = 0; + tagtype = (tag_t)0; +} + + +StreamInfo::StreamInfo () +{ + memset ( &simple, 0, sizeof (simple) ); + tagitem_count = 0; + tagtype = (tag_t)0; + tagitems = NULL; + filename = NULL; +} + + +void +StreamInfo::SetFilename ( const char *fn ) +{ + if ( filename ) free ( filename ); + filename = strdup ( fn ); +} + + +const char * +StreamInfo::GetFilename () +{ + return filename ? filename : ""; +} + + +// return pointer to value in tag field +static char * +TagValue(const char* item, const StreamInfo* Info) +{ + size_t i; + + for ( i = 0; i < Info->tagitem_count; i++ ) { + // Are items case sensitive? + if (!strcasecmp(item, Info->tagitems[i].Item)) + return (char*)Info->tagitems[i].Value; + } + + return 0; +} + + +// add new field to tagdata +static int +NewTagField(const char* item, const size_t itemsize, const char* value, + const size_t valuesize, const unsigned int flags, StreamInfo* Info, + const enum tag_rel reliability) +{ + size_t itemnum = Info->tagitem_count++; + + // no real error handling yet + Info->tagitems = (TagItem*) realloc ( Info->tagitems, Info->tagitem_count * sizeof (TagItem) ); + if ( Info->tagitems == NULL ) { + Info->tagitem_count = 0; + return 1; + } + Info->tagitems[itemnum].Item = (char*)malloc ( itemsize + 1 ); + if ( Info->tagitems[itemnum].Item == NULL ) { // couldn't allocate memory, revert to original items + Info->tagitems = (TagItem*) realloc ( Info->tagitems, --Info->tagitem_count * sizeof (TagItem) ); + return 1; + } + Info->tagitems[itemnum].Value = (char*)malloc ( valuesize + 1 ); + if ( Info->tagitems[itemnum].Value == NULL ) { // couldn't allocate memory, revert to original items + free ( Info->tagitems[itemnum].Item ); + Info->tagitems = (TagItem*) realloc ( Info->tagitems, --Info->tagitem_count * sizeof (TagItem) ); + return 1; + } + memcpy ( Info->tagitems[itemnum].Item , item , itemsize ); + memcpy ( Info->tagitems[itemnum].Value, value, valuesize ); + + Info->tagitems[itemnum].Item [itemsize] = '\0'; + Info->tagitems[itemnum].Value[valuesize] = '\0'; + + Info->tagitems[itemnum].ItemSize = itemsize; + Info->tagitems[itemnum].ValueSize = valuesize; + Info->tagitems[itemnum].Flags = flags; + Info->tagitems[itemnum].Reliability = reliability; + + return 0; +} + + +// replace old value in tagdata field +static int +ReplaceTagField(const char* value, const size_t valuesize, const unsigned int flags, + StreamInfo* Info, size_t itemnum, const enum tag_rel reliability) +{ + // no real error handling yet + free ( Info->tagitems[itemnum].Value ); + Info->tagitems[itemnum].Value = (char*)malloc ( valuesize + 1 ); + if ( Info->tagitems[itemnum].Value == NULL ) // couldn't allocate memory + return 1; + memcpy ( Info->tagitems[itemnum].Value, value, valuesize ); + + Info->tagitems[itemnum].Value[valuesize] = '\0'; + Info->tagitems[itemnum].ValueSize = valuesize; + Info->tagitems[itemnum].Flags = flags; + Info->tagitems[itemnum].Reliability = reliability; + return 0; +} + + +#if 0 +// insert item to tagdata. calls either new or replace +static int +InsertTagField(const char* item, size_t itemsize, const char* value, + size_t valuesize, const unsigned int flags, StreamInfo* Info) +{ + size_t i; + + if ( itemsize == 0 ) itemsize = strlen ( item ); // autodetect size + if ( valuesize == 0 ) valuesize = strlen ( value ); // autodetect size + + for ( i = 0; i < Info->tagitem_count; i++ ) { + // are items case sensitive? + if (!strcasecmp(item, Info->tagitems[i].Item)) // replace value of first item found + return ReplaceTagField ( value, valuesize, flags, Info, i, (tag_rel)0 ); + } + + return NewTagField ( item, itemsize, value, valuesize, flags, Info, (tag_rel)0 );// insert new field +} +#endif + + +// insert item to tagdata but only if reliability > previous tag's reliability +static int +InsertTagFieldLonger(const char* item, size_t itemsize, const char* value, + size_t valuesize, const unsigned int flags, StreamInfo* Info, + const enum tag_rel reliability) +{ + size_t i; + + if ( itemsize == 0 ) itemsize = strlen ( item ); // autodetect size + if ( valuesize == 0 ) valuesize = strlen ( value ); // autodetect size + + for ( i = 0; i < Info->tagitem_count; i++ ) { + // are items case sensitive? + if (!strcasecmp(item, Info->tagitems[i].Item)) { + if ( reliability > Info->tagitems[i].Reliability ) // replace value of first item found + return ReplaceTagField ( value, valuesize, flags, Info, i, reliability ); + else + return 0; + } + } + + return NewTagField ( item, itemsize, value, valuesize, flags, Info, reliability ); // insert new field +} + +#if 0 +// Convert UNICODE to UTF-8 +// Return number of bytes written +static int +unicodeToUtf8(const uint16/*WCHAR*/* lpWideCharStr, char* lpMultiByteStr, int cwcChars) +{ + const unsigned short* pwc = (unsigned short *)lpWideCharStr; + unsigned char* pmb = (unsigned char *)lpMultiByteStr; + const unsigned short* pwce; + size_t cBytes = 0; + + if ( cwcChars >= 0 ) { + pwce = pwc + cwcChars; + } else { + pwce = (unsigned short *)((size_t)-1); + } + + while ( pwc < pwce ) { + unsigned short wc = *pwc++; + + if ( wc < 0x00000080 ) { + *pmb++ = (char)wc; + cBytes++; + } else + if ( wc < 0x00000800 ) { + *pmb++ = (char)(0xC0 | ((wc >> 6) & 0x1F)); + cBytes++; + *pmb++ = (char)(0x80 | (wc & 0x3F)); + cBytes++; + } else + if ( wc < 0x00010000 ) { + *pmb++ = (char)(0xE0 | ((wc >> 12) & 0x0F)); + cBytes++; + *pmb++ = (char)(0x80 | ((wc >> 6) & 0x3F)); + cBytes++; + *pmb++ = (char)(0x80 | (wc & 0x3F)); + cBytes++; + } + if ( wc == L'\0' ) + return cBytes; + } + + return cBytes; +} + +// Convert UTF-8 coded string to UNICODE +// Return number of characters converted +static int +utf8ToUnicode(const char* lpMultiByteStr, uint16/*WCHAR*/* lpWideCharStr, int cmbChars) +{ + const unsigned char* pmb = (unsigned char *)lpMultiByteStr; + unsigned short* pwc = (unsigned short *)lpWideCharStr; + const unsigned char* pmbe; + size_t cwChars = 0; + + if ( cmbChars >= 0 ) { + pmbe = pmb + cmbChars; + } else { + pmbe = (unsigned char *)((size_t)-1); + } + + while ( pmb < pmbe ) { + char mb = *pmb++; + unsigned int cc = 0; + unsigned int wc; + + while ( (cc < 7) && (mb & (1 << (7 - cc)))) { + cc++; + } + + if ( cc == 1 || cc > 6 ) // illegal character combination for UTF-8 + continue; + + if ( cc == 0 ) { + wc = mb; + } else { + wc = (mb & ((1 << (7 - cc)) - 1)) << ((cc - 1) * 6); + while ( --cc > 0 ) { + if ( pmb == pmbe ) // reached end of the buffer + return cwChars; + mb = *pmb++; + if ( ((mb >> 6) & 0x03) != 2 ) // not part of multibyte character + return cwChars; + wc |= (mb & 0x3F) << ((cc - 1) * 6); + } + } + + if ( wc & 0xFFFF0000 ) + wc = L'?'; + *pwc++ = wc; + cwChars++; + if ( wc == L'\0' ) + return cwChars; + } + + return cwChars; +} +#endif + +// convert Windows ANSI to UTF-8 +static int +ConvertANSIToUTF8(const char *ansi, char *utf8) +{ + // ToDo: + return 0; +} + +#if 0 +static int +ConvertTagFieldToUTF8(StreamInfo *Info, size_t itemnum) +{ + // ToDo: + return 0; +} +#endif + +// replace list separator characters in tag field +static int +ReplaceListSeparator(const char* old_sep, const char* new_sep, StreamInfo* Info, + size_t itemnum) +{ + unsigned char* new_value; + unsigned char* p; + size_t os_len; + size_t ns_len; + size_t count; + size_t new_len; + size_t i; + int error; + + if ( Info->tagitems[itemnum].Flags & 1<<1 ) // data in binary + return 0; + + os_len = strlen ( old_sep ); + ns_len = strlen ( new_sep ); + if ( os_len == 0 ) os_len = 1; // allow null character + if ( ns_len == 0 ) ns_len = 1; + + if ( Info->tagitems[itemnum].Value == NULL || // nothing to do + Info->tagitems[itemnum].ValueSize == 0 ) + return 0; + + count = 0; + for ( i = 0; i < Info->tagitems[itemnum].ValueSize - os_len + 1; i++ ) { + if ( memcmp ( Info->tagitems[itemnum].Value+i, old_sep, os_len ) == 0 ) + count++; + } + + if ( count == 0 ) + return 0; + + new_len = Info->tagitems[itemnum].ValueSize - (count * os_len) + (count * ns_len); + if ( (new_value = (unsigned char *)malloc ( new_len )) == NULL ) + return 1; + + p = new_value; + for ( i = 0; i < Info->tagitems[itemnum].ValueSize; i++ ) { + if ( i + os_len - 1 >= Info->tagitems[itemnum].ValueSize || + memcmp ( Info->tagitems[itemnum].Value+i, old_sep, os_len ) != 0 ) { + *p++ = Info->tagitems[itemnum].Value[i]; + } else { + memcpy ( p, new_sep, ns_len ); + p += ns_len; + i += os_len - 1; + } + } + + error = ReplaceTagField ( (const char*)new_value, new_len, Info->tagitems[itemnum].Flags, Info, itemnum, Info->tagitems[itemnum].Reliability ); + + free ( new_value ); + + return error; +} + + +static int +GenreToInteger(const char *GenreStr) +{ + size_t i; + + for ( i = 0; i < sizeof(GenreList) / sizeof(*GenreList); i++ ) { + if (!strcasecmp(GenreStr, GenreList[i])) + return i; + } + + return -1; +} + + +static void +GenreToString(char *GenreStr, const unsigned int genre) +{ + GenreStr [0] = '\0'; + if ( genre < NO_GENRES ) + strcpy ( GenreStr, GenreList [genre] ); +} + + +/* + * Copies src to dst. Copying is stopped at `\0' char is detected or if + * len chars are copied. + * Trailing blanks are removed and the string is `\0` terminated. + */ + +static void +memcpy_crop(char* dst, const char* src, size_t len) +{ + size_t i; + + for ( i = 0; i < len; i++ ) + if ( src[i] != '\0' ) + dst[i] = src[i]; + else + break; + + // dst[i] points behind the string contents + while ( i > 0 && dst [i-1] == ' ' ) + i--; + + dst [i] = '\0'; +} + + +#if 0 +// replaces % sequences with real characters +static void +fix_percentage_sequences(char *string) +{ + char temp[PATH_MAX]; + char* t = temp; + char* s = string; + int value; + int b1, b2; //, b3, b4; + int v1, v2; //, v3, v4; + + do { + value = *s++; + + if ( value == '%' ) { + if ( *s != '\0' ) b1 = *s++; + else b1 = '\0'; + if ( *s != '\0' ) b2 = *s++; + else b2 = '\0'; + + if ( ((b1 >= '0' && b1 <= '9') || (b1 >= 'A' && b1 <= 'F')) && + ((b2 >= '0' && b2 <= '9') || (b2 >= 'A' && b2 <= 'F')) ) { + + if ( b1 <= '9' ) v1 = b1 - '0'; + else v1 = b1 - 'A' + 10; + if ( b2 <= '9' ) v2 = b2 - '0'; + else v2 = b2 - 'A' + 10; + + if ( v1 == 0 && v2 == 0 ) { // %00xx + /* + if ( *s != '\0' ) b1 = *s++; + else b1 = '\0'; + if ( *s != '\0' ) b2 = *s++; + else b2 = '\0'; + if ( *s != '\0' ) b3 = *s++; + else b2 = '\0'; + if ( *s != '\0' ) b4 = *s++; + else b4 = '\0'; + + if ( b1 <= '9' ) v1 = b1 - '0'; + else v1 = b1 - 'A' + 10; + if ( b2 <= '9' ) v2 = b2 - '0'; + else v2 = b2 - 'A' + 10; + if ( b3 <= '9' ) v3 = b3 - '0'; + else v3 = b3 - 'A' + 10; + if ( b4 <= '9' ) v4 = b4 - '0'; + else v4 = b4 - 'A' + 10; + + if ( v1 != 0 || v2 != 0 ) { + *t++ = ' '; // no multibyte support, unknown character + } else { // %0000+xxxx+ + *t++ = ' '; + + while ( *s && ((*s >= '0' && *s <= '9') || (*s >= 'A' && *s <= 'F')) ) + s++; + } + */ + + *t++ = ' '; + + while ( *s && ((*s >= '0' && *s <= '9') || (*s >= 'A' && *s <= 'F')) ) + s++; + } else { // %xx + *t++ = (v1 << 4) + v2; + } + } else { // %aa + *t++ = '%'; + *t++ = b1; + *t++ = b2; + } + } else { + *t++ = value; + } + } while ( value != '\0' ); + + strcpy ( string, temp ); +} +#endif + + +// searches and reads a ID3v1 tag +int StreamInfo::ReadID3v1Tag(BPositionIO *stream) +{ +/* unsigned */char tmp [128]; +/* unsigned */char value [32]; + char utf8[32*2]; + + if (stream->Seek(simple.TagOffset - sizeof(tmp), SEEK_SET) < B_OK) + return 0; + if (stream->Read(tmp, sizeof(tmp)) != sizeof(tmp)) + return 0; + // check for id3-tag + if (memcmp(tmp, "TAG", 3) != 0) + return 0; + + memcpy_crop ( value, tmp + 3, 30 ); + if ( value[0] != '\0' ) { + ConvertANSIToUTF8 ( value, utf8 ); + InsertTagFieldLonger ( APE_TAG_FIELD_TITLE , 0, utf8, 0, 0, this, ID3v1 ); + } + memcpy_crop ( value, tmp + 33, 30 ); + if ( value[0] != '\0' ) { + ConvertANSIToUTF8 ( value, utf8 ); + InsertTagFieldLonger ( APE_TAG_FIELD_ARTIST , 0, utf8, 0, 0, this, ID3v1 ); + } + memcpy_crop ( value, tmp + 63, 30 ); + if ( value[0] != '\0' ) { + ConvertANSIToUTF8 ( value, utf8 ); + InsertTagFieldLonger ( APE_TAG_FIELD_ALBUM , 0, utf8, 0, 0, this, ID3v1 ); + } + memcpy_crop ( value, tmp + 93, 4 ); + if ( value[0] != '\0' ) { + ConvertANSIToUTF8 ( value, utf8 ); + InsertTagFieldLonger ( APE_TAG_FIELD_YEAR , 0, utf8, 0, 0, this, ID3v1 ); + } + memcpy_crop ( value, tmp + 97, 30 ); + if ( value[0] != '\0' ) { + ConvertANSIToUTF8 ( value, utf8 ); + InsertTagFieldLonger ( APE_TAG_FIELD_COMMENT, 0, utf8, 0, 0, this, ID3v1 ); + } + + if ( tmp[125] == 0 ) { + sprintf ( value, "%d", tmp[126] ); + if ( value[0] != '\0' && atoi (value) != 0 ) { + ConvertANSIToUTF8 ( value, utf8 ); + InsertTagFieldLonger ( APE_TAG_FIELD_TRACK, 0, utf8, 0, 0, this, ID3v1 ); + } + } + GenreToString ( value, tmp[127] ); + if ( value[0] != '\0' ) { + ConvertANSIToUTF8 ( value, utf8 ); + InsertTagFieldLonger ( APE_TAG_FIELD_GENRE , 0, utf8, 0, 0, this, ID3v1 ); + } + + simple.TagOffset -= 128; + tagtype = ID3v1_tag; + + return 0; +} + + +struct APETagFooterStruct { + unsigned char ID [8]; // should equal 'APETAGEX' + unsigned char Version [4]; // 1000 = version 1.0, 2000 = version 2.0 + unsigned char Length [4]; // complete size of the tag, including footer, excluding header + unsigned char TagCount [4]; // number of fields in the tag + unsigned char Flags [4]; // tag flags (none currently defined) + unsigned char Reserved [8]; // reserved for later use +}; + + +static unsigned long +Read_LE_Uint32 ( const unsigned char* p ) +{ + return ((unsigned long)p[0] << 0) | + ((unsigned long)p[1] << 8) | + ((unsigned long)p[2] << 16) | + ((unsigned long)p[3] << 24); +} + +/*static void +Write_LE_Uint32 ( unsigned char* p, const unsigned long value ) +{ + p[0] = (unsigned char) (value >> 0); + p[1] = (unsigned char) (value >> 8); + p[2] = (unsigned char) (value >> 16); + p[3] = (unsigned char) (value >> 24); +} +*/ + +int +StreamInfo::ReadAPE1Tag(BPositionIO *stream) +{ + unsigned long vsize; + unsigned long isize; + unsigned long flags; + /*unsigned */char* buff; + /*unsigned */char* p; + /*unsigned */char* end; + char* utf8; + struct APETagFooterStruct T; + unsigned long TagLen; + unsigned long TagCount; + + if (stream->Seek(simple.TagOffset - sizeof T, SEEK_SET) < B_OK) + return 0; + if (stream->Read(&T, sizeof T) != sizeof T) + return 0; + if ( memcmp ( T.ID, "APETAGEX", sizeof T.ID ) != 0 ) + return 0; + if ( Read_LE_Uint32 (T.Version) != 1000 ) + return 0; + TagLen = Read_LE_Uint32 (T.Length); + if ( TagLen <= sizeof T ) + return 0; + if (stream->Seek(simple.TagOffset - TagLen, SEEK_SET ) < B_OK) + return 0; + buff = (char *)malloc ( TagLen ); + if ( buff == NULL ) + return 1; + if (stream->Read(buff, TagLen - sizeof(T)) != ssize_t(TagLen - sizeof(T))) { + free(buff); + return 0; + } + + TagCount = Read_LE_Uint32 (T.TagCount); + end = buff + TagLen - sizeof (T); + for ( p = buff; p < end /*&& *p */ && TagCount--; ) { + vsize = Read_LE_Uint32 ( (unsigned char *) p ); p += 4; + flags = Read_LE_Uint32 ( (unsigned char *) p ); p += 4; + isize = strlen(p); + + if ( vsize > 0 ) { + if ( (utf8 = (char*)malloc ( (vsize + 1) * 3 )) == NULL ) { + free ( buff ); + return 1; + } + ConvertANSIToUTF8 ( p + isize + 1, utf8 ); + InsertTagFieldLonger ( p, isize, utf8, 0, 0, this, APE1 ); // flags not used with APE 1.0 + free ( utf8 ); + } + p += isize + 1 + vsize; + } + + simple.TagOffset -= TagLen; + tagtype = APE1_tag; + + free(buff); + + return 0; +} + + +int +StreamInfo::ReadAPE2Tag(BPositionIO *stream) +{ + unsigned long vsize; + unsigned long isize; + unsigned long flags; + /*unsigned */char* buff; + /*unsigned */char* p; + /*unsigned */char* end; + struct APETagFooterStruct T; + unsigned long TagLen; + unsigned long TagCount; + size_t i; + + if (stream->Seek(simple.TagOffset - sizeof(T), SEEK_SET) < B_OK) + return 0; + if (stream->Read(&T, sizeof(T)) != sizeof(T)) + return 0; + if (memcmp(T.ID, "APETAGEX", sizeof(T.ID)) != 0) + return 0; + if (Read_LE_Uint32(T.Version) != 2000) + return 0; + TagLen = Read_LE_Uint32(T.Length); + if (TagLen <= sizeof(T)) + return 0; + if (stream->Seek(simple.TagOffset - TagLen, SEEK_SET) < B_OK) + return 0; + buff = (char *)malloc(TagLen); + if (buff == NULL) + return 1; + if (stream->Read(buff, TagLen - sizeof(T)) != ssize_t(TagLen - sizeof(T))) { + free(buff); + return 0; + } + + TagCount = Read_LE_Uint32(T.TagCount); + end = buff + TagLen - sizeof(T); + for (p = buff; p < end /*&& *p */ && TagCount--;) { + vsize = Read_LE_Uint32((unsigned char *)p); p += 4; + flags = Read_LE_Uint32((unsigned char *)p); p += 4; + isize = strlen(p); + + if (vsize > 0) + InsertTagFieldLonger(p, isize, p + isize + 1, vsize, flags, this, APE2); + p += isize + 1 + vsize; + } + + simple.TagOffset -= TagLen; + tagtype = APE2_tag; + + free (buff); + + for (i = 0; i < tagitem_count; i++) { + if (ReplaceListSeparator("\0", ListSeparator, this, i) != 0) + return 2; + } + + if (Read_LE_Uint32(T.Flags) & 1<<31) { // Tag contains header + simple.TagOffset -= sizeof (T); + } else { // Check if footer was incorrect + if (stream->Seek(simple.TagOffset - sizeof(T), SEEK_SET ) < B_OK) + return 0; + if (stream->Read(&T, sizeof(T)) != sizeof(T)) + return 0; + if (memcmp(T.ID, "APETAGEX", sizeof(T.ID)) != 0) + return 0; + if (Read_LE_Uint32(T.Version) != 2000) + return 0; + if (Read_LE_Uint32(T.Flags) & 1<<29 ) // This is header + simple.TagOffset -= sizeof(T); + } + + return 0; +} + + +bool +_validForID3(const char *string, int maxsize) +{ + const unsigned char* p = (unsigned char *)string; + + while (*p) { + // only ASCII characters are reliable in ID3v1 + if (*p++ >= 0x80) + return false; + } + + return ( ((char*)p - string) <= maxsize ); +} + +// checks if ID3v1 tag can store all tag information +// return 0 if can, 1 if can't +int +CheckID3V1TagDataLoss(const StreamInfo *Info) +{ + const char *id3v1_items[] = { + APE_TAG_FIELD_TITLE, // 0 + APE_TAG_FIELD_ARTIST, // 1 + APE_TAG_FIELD_ALBUM, // 2 + APE_TAG_FIELD_YEAR, // 3 + APE_TAG_FIELD_COMMENT, // 4 + APE_TAG_FIELD_TRACK, // 5 + APE_TAG_FIELD_GENRE // 6 + }; + char* value; + size_t i, j; + + if ( (value = TagValue ( APE_TAG_FIELD_TRACK, Info )) ) { + char* p = value; + while ( *p ) { + if ( *p < '0' || *p > '9' ) return 1; // not a number + p++; + } + if ( atoi (value) < 0 || // number won't fit in byte + atoi (value) > 255 ) + return 1; + } + + if ( ( value = TagValue ( APE_TAG_FIELD_GENRE, Info )) ) { + if ( value[0] != '\0' && (unsigned int)GenreToInteger (value) >= NO_GENRES ) // non-standard genre + return 1; + } + + for ( i = 0; i < Info->tagitem_count; i++ ) { + bool bFound = false; + for ( j = 0; j < sizeof (id3v1_items) / sizeof (*id3v1_items); j++ ) { + if (!strcasecmp(Info->tagitems[i].Item, id3v1_items[j])) { + int maxlen; + switch ( j ) { + case 3: // Year + maxlen = 4; + break; + case 4: // Comment + value = TagValue ( APE_TAG_FIELD_TRACK, Info ); + if ( value && strcmp ( value, "" ) != 0 ) + maxlen = 28; + else + maxlen = 30; + break; + default: + maxlen = 30; + break; + } + if ( !_validForID3 ( Info->tagitems[i].Value, maxlen ) ) + return 1; + bFound = TRUE; + break; + } + } + if ( !bFound ) return 1; // field not possible in ID3v1 + } + + return 0; +} + + +// scan file for all supported tags and read them +int +StreamInfo::ReadTags(BPositionIO *fp) +{ + off_t TagOffs; + + do { + TagOffs = simple.TagOffset; + ReadAPE1Tag(fp); + ReadAPE2Tag(fp); + ReadID3v1Tag(fp); + } while (TagOffs != simple.TagOffset); + + return 0; +} + + +// searches for a ID3v2-tag and reads the length (in bytes) of it +// -1 on errors of any kind + +long +JumpID3v2(BPositionIO *fp) +{ + unsigned char tmp [10]; + unsigned int Unsynchronisation; // ID3v2.4-flag + unsigned int ExtHeaderPresent; // ID3v2.4-flag + unsigned int ExperimentalFlag; // ID3v2.4-flag + unsigned int FooterPresent; // ID3v2.4-flag + long ret; + + fp->Read(tmp, sizeof(tmp)); + + // check id3-tag + if (memcmp(tmp, "ID3", 3) != 0) + return 0; + + // read flags + Unsynchronisation = tmp[5] & 0x80; + ExtHeaderPresent = tmp[5] & 0x40; + ExperimentalFlag = tmp[5] & 0x20; + FooterPresent = tmp[5] & 0x10; + + if ( tmp[5] & 0x0F ) + return -1; // not (yet???) allowed + if ( (tmp[6] | tmp[7] | tmp[8] | tmp[9]) & 0x80 ) + return -1; // not allowed + + // read HeaderSize (syncsave: 4 * $0xxxxxxx = 28 significant bits) + ret = tmp[6] << 21; + ret += tmp[7] << 14; + ret += tmp[8] << 7; + ret += tmp[9] ; + ret += 10; + if (FooterPresent) + ret += 10; + + return ret; +} diff --git a/src/add-ons/media/plugins/musepack/mpc/idtag.h b/src/add-ons/media/plugins/musepack/mpc/idtag.h new file mode 100644 index 0000000000..a8fa75b86a --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/idtag.h @@ -0,0 +1,110 @@ +#ifndef _idtag_h_ +#define _idtag_h_ + +#include + +class BPositionIO; +class StreamInfo; + +/* D E F I N E S */ + +#define NO_GENRES 148 + +// APE Tag item names +#define APE_TAG_FIELD_TITLE "Title" +#define APE_TAG_FIELD_SUBTITLE "Subtitle" +#define APE_TAG_FIELD_ARTIST "Artist" +#define APE_TAG_FIELD_ALBUM "Album" +#define APE_TAG_FIELD_DEBUTALBUM "Debut Album" +#define APE_TAG_FIELD_PUBLISHER "Publisher" +#define APE_TAG_FIELD_CONDUCTOR "Conductor" +#define APE_TAG_FIELD_COMPOSER "Composer" +#define APE_TAG_FIELD_COMMENT "Comment" +#define APE_TAG_FIELD_YEAR "Year" +#define APE_TAG_FIELD_RECORDDATE "Record Date" +#define APE_TAG_FIELD_RECORDLOCATION "Record Location" +#define APE_TAG_FIELD_TRACK "Track" +#define APE_TAG_FIELD_GENRE "Genre" +#define APE_TAG_FIELD_COVER_ART_FRONT "Cover Art (front)" +#define APE_TAG_FIELD_NOTES "Notes" +#define APE_TAG_FIELD_LYRICS "Lyrics" +#define APE_TAG_FIELD_COPYRIGHT "Copyright" +#define APE_TAG_FIELD_PUBLICATIONRIGHT "Publicationright" +#define APE_TAG_FIELD_FILE "File" +#define APE_TAG_FIELD_MEDIA "Media" +#define APE_TAG_FIELD_EANUPC "EAN/UPC" +#define APE_TAG_FIELD_ISRC "ISRC" +#define APE_TAG_FIELD_RELATED_URL "Related" +#define APE_TAG_FIELD_ABSTRACT_URL "Abstract" +#define APE_TAG_FIELD_BIBLIOGRAPHY_URL "Bibliography" +#define APE_TAG_FIELD_BUY_URL "Buy URL" +#define APE_TAG_FIELD_ARTIST_URL "Artist URL" +#define APE_TAG_FIELD_PUBLISHER_URL "Publisher URL" +#define APE_TAG_FIELD_FILE_URL "File URL" +#define APE_TAG_FIELD_COPYRIGHT_URL "Copyright URL" +#define APE_TAG_FIELD_INDEX "Index" +#define APE_TAG_FIELD_INTROPLAY "Introplay" +#define APE_TAG_FIELD_MJ_METADATA "Media Jukebox Metadata" +#define APE_TAG_FIELD_DUMMY "Dummy" + +enum tag_t { + auto_tag = -1, + no_tag = 0, + ID3v1_tag = 1, + APE1_tag = 2, + APE2_tag = 3, + Ogg_tag = 4, + ID3v2 = 16, + guessed_tag = 255, +}; + +// reliability of tag information +enum tag_rel { + guess = 1, + ID3v1 = 10, + APE1 = 19, + APE2 = 20 +}; + +/* V A R I A B L E S */ +//extern const char* GenreList []; // holds the genres available for ID3 + +/* F U N C T I O N S */ + +// Function that tries to guess tag information from filename +//int GuessTag ( const char* filename, StreamInfo* Info ); + +// Read tag data +//int ReadID3v1Tag ( FILE* fp, StreamInfo* Info ); // reads ID3v1 tag +//int ReadAPE1Tag ( FILE* fp, StreamInfo* Info ); // reads APE 1.0 tag +//int ReadAPE2Tag ( FILE* fp, StreamInfo* Info ); // reads APE 2.0 tag +//int ReadTags ( FILE* fp, StreamInfo* Info ); // reads all tags from file + + +// Calculates start of file +long JumpID3v2 ( BPositionIO *file ); +/* +// add new field to tagdata +int NewTagField ( const char* item, const size_t itemsize, const char* value, const size_t valuesize, const unsigned int flags, StreamInfo* Info, const enum tag_rel reliability ); + +// replace old value in tagdata field +int ReplaceTagField ( const char* value, const size_t valuesize, const unsigned int flags, StreamInfo* Info, size_t itemnum, const enum tag_rel reliability ); + +// Free all tag fields from memory +//void FreeTagFields ( StreamInfo* Info );//obsolete, use StreamInfo::Clear() + +// insert item to tagdata. calls either new or replace +int InsertTagField ( const char* item, size_t itemsize, const char* value, size_t valuesize, const unsigned int flags, StreamInfo* Info ); + +// insert item to tagdata but only if reliability > previous tag's reliability +int InsertTagFieldLonger ( const char* item, size_t itemsize, const char* value, size_t valuesize, const unsigned int flags, StreamInfo* Info, const enum tag_rel reliability ); + +// Copy item to dest, maximum length to copy is count +int CopyTagValue ( char* dest, const char* item, const StreamInfo* Info, size_t count ); + +// Return pointer to item or NULL on error +char* TagValue ( const char* item, const StreamInfo* Info ); + +int GenreToInteger ( const char* GenreStr); +*/ +#endif diff --git a/src/add-ons/media/plugins/musepack/mpc/in_mpc.cpp b/src/add-ons/media/plugins/musepack/mpc/in_mpc.cpp new file mode 100644 index 0000000000..a5ede840fe --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/in_mpc.cpp @@ -0,0 +1,207 @@ +/* Winamp plugin for ".mpc Musepack", based on miniSDK by Nullsoft */ +/* by Andree Buschmann, contact: Andree.Buschmann@web.de */ +/* --------- ".mpc Musepack" is a registered trademark ---------- */ + +#include + +/************************ DEFINES ************************/ +//#define WINAMP +//#define WM_WA_MPEG_EOF (WM_USER + 2) // post this to the main window at end of file +//#define NCH_MAX 2 // number of channels (only stereo!) +//#define BPS 16 // bits per sample (only 16 bps!) +//#define BYTES 4 // = (NCH_MAX*(BPS/8)) -> number of bytes needed for one stereo/16bit-sample +//#define M_PI 3.141592653589793238462643383276 + + // 2nd "*2" for reconstruction of exact filelength + +/*********************** INCLUDES ************************/ +#include "in_mpc.h" +#include "mpc_dec.h" +#include "idtag.h" + +#include + +//SettingsMPC PluginSettings; // AB: PluginSettings holds the parameters for the plugin-configuration + +static const char* +Stringify ( unsigned int profile ) // profile is 0...15, where 7...13 is used +{ + static const char na [] = "n.a."; + static const char* Names [] = { + na, "'Unstable/Experimental'", na, na, + na, "below 'Telephone'", "below 'Telephone'", "'Telephone'", + "'Thumb'", "'Radio'", "'Standard'", "'Xtreme'", + "'Insane'", "'BrainDead'", "above 'BrainDead'", "above 'BrainDead'" + }; + + return profile >= sizeof(Names)/sizeof(*Names) ? na : Names [profile]; +} + +// read information from SV8 header +int StreamInfo::ReadHeaderSV8 ( BPositionIO* fp ) +{ +// Update (simple.StreamVersion); + return 0; +} + +// read information from SV7 header +int StreamInfo::ReadHeaderSV7 ( BPositionIO* fp ) +{ + const long samplefreqs [4] = { 44100, 48000, 37800, 32000 }; + + unsigned int HeaderData [8]; + unsigned short EstimatedPeakTitle = 0; + + if (simple.StreamVersion > 0x71) { +// Update (simple.StreamVersion); + return 0; + } + + if (fp->Seek(simple.HeaderPosition, SEEK_SET ) < B_OK) // seek to header start + return ERROR_CODE_FILE; + if (fp->Read(HeaderData, sizeof(HeaderData)) != sizeof HeaderData) + return ERROR_CODE_FILE; + + simple.Bitrate = 0; + simple.Frames = HeaderData[1]; + simple.IS = 0; + simple.MS = (HeaderData[2] >> 30) & 0x0001; + simple.MaxBand = (HeaderData[2] >> 24) & 0x003F; + simple.BlockSize = 1; + simple.Profile = (HeaderData[2] << 8) >> 28; + simple.ProfileName = Stringify ( simple.Profile ); + + simple.SampleFreq = samplefreqs [(HeaderData[2]>>16) & 0x0003]; + + EstimatedPeakTitle = HeaderData[2] & 0xFFFF; // read the ReplayGain data + simple.GainTitle = (HeaderData[3] >> 16) & 0xFFFF; + simple.PeakTitle = HeaderData[3] & 0xFFFF; + simple.GainAlbum = (HeaderData[4] >> 16) & 0xFFFF; + simple.PeakAlbum = HeaderData[4] & 0xFFFF; + + simple.IsTrueGapless = (HeaderData[5] >> 31) & 0x0001; // true gapless: used? + simple.LastFrameSamples = (HeaderData[5] >> 20) & 0x07FF; // true gapless: valid samples for last frame + + simple.EncoderVersion = (HeaderData[6] >> 24) & 0x00FF; + if ( simple.EncoderVersion == 0 ) { + sprintf ( simple.Encoder, "Buschmann 1.7.0...9, Klemm 0.90...1.05" ); + } else { + switch ( simple.EncoderVersion % 10 ) { + case 0: + sprintf ( simple.Encoder, "Release %u.%u", simple.EncoderVersion/100, simple.EncoderVersion/10%10 ); + break; + case 2: case 4: case 6: case 8: + sprintf ( simple.Encoder, "Beta %u.%02u", simple.EncoderVersion/100, simple.EncoderVersion%100 ); + break; + default: + sprintf ( simple.Encoder, "--Alpha-- %u.%02u", simple.EncoderVersion/100, simple.EncoderVersion%100 ); + break; + } + } + + if ( simple.PeakTitle == 0 ) // there is no correct PeakTitle contained within header + simple.PeakTitle = (unsigned short)(EstimatedPeakTitle * 1.18); + if ( simple.PeakAlbum == 0 ) + simple.PeakAlbum = simple.PeakTitle; // no correct PeakAlbum, use PeakTitle + + //simple.SampleFreq = 44100; // AB: used by all files up to SV7 + simple.Channels = 2; + + return ERROR_CODE_OK; +} + +// read information from SV4-SV6 header +int +StreamInfo::ReadHeaderSV6(BPositionIO *fp) +{ + unsigned int HeaderData [8]; + + if (fp->Seek(simple.HeaderPosition, SEEK_SET ) < B_OK) // seek to header start + return ERROR_CODE_FILE; + if (fp->Read(HeaderData, sizeof HeaderData) != sizeof HeaderData) + return ERROR_CODE_FILE; + + simple.Bitrate = (HeaderData[0] >> 23) & 0x01FF; // read the file-header (SV6 and below) + simple.IS = (HeaderData[0] >> 22) & 0x0001; + simple.MS = (HeaderData[0] >> 21) & 0x0001; + simple.StreamVersion = (HeaderData[0] >> 11) & 0x03FF; + simple.MaxBand = (HeaderData[0] >> 6) & 0x001F; + simple.BlockSize = (HeaderData[0] ) & 0x003F; + simple.Profile = 0; + simple.ProfileName = Stringify(~0); + if ( simple.StreamVersion >= 5 ) + simple.Frames = HeaderData[1]; // 32 bit + else + simple.Frames = (HeaderData[1]>>16); // 16 bit + + simple.GainTitle = 0; // not supported + simple.PeakTitle = 0; + simple.GainAlbum = 0; + simple.PeakAlbum = 0; + + simple.LastFrameSamples = 0; + simple.IsTrueGapless = 0; + + simple.EncoderVersion = 0; + simple.Encoder[0] = '\0'; + + if ( simple.StreamVersion == 7 ) return ERROR_CODE_SV7BETA; // are there any unsupported parameters used? + if ( simple.Bitrate != 0 ) return ERROR_CODE_CBR; + if ( simple.IS != 0 ) return ERROR_CODE_IS; + if ( simple.BlockSize != 1 ) return ERROR_CODE_BLOCKSIZE; + + if ( simple.StreamVersion < 6 ) // Bugfix: last frame was invalid for up to SV5 + simple.Frames -= 1; + + simple.SampleFreq = 44100; // AB: used by all files up to SV7 + simple.Channels = 2; + + if ( simple.StreamVersion < 4 || simple.StreamVersion > 7 ) + return ERROR_CODE_INVALIDSV; + + return ERROR_CODE_OK; +} + +// reads file header and tags +int StreamInfo::ReadStreamInfo ( BPositionIO* fp) +{ + unsigned int HeaderData[1]; + int Error = 0; + + //memset ( &simple, 0, sizeof (BasicData) ); // Reset Info-Data + + if ( (simple.HeaderPosition = JumpID3v2 (fp)) < 0 ) // get header position + return ERROR_CODE_FILE; + + if (fp->Seek(simple.HeaderPosition, SEEK_SET) < B_OK) // seek to first byte of mpc data + return ERROR_CODE_FILE; + if (fp->Read(HeaderData, sizeof HeaderData) != sizeof HeaderData) + return ERROR_CODE_FILE; + if (fp->Seek(0L, SEEK_END) < B_OK) // get filelength + return ERROR_CODE_FILE; + simple.TotalFileLength = fp->Position(); + simple.TagOffset = simple.TotalFileLength; + + if ( memcmp ( HeaderData, "MP+", 3 ) == 0 ) { // check version + simple.StreamVersion = HeaderData[0] >> 24; + + if ( (simple.StreamVersion & 15) >= 8 ) // StreamVersion 8 + Error = ReadHeaderSV8 ( fp ); + else if ( (simple.StreamVersion & 15) == 7 ) // StreamVersion 7 + Error = ReadHeaderSV7 ( fp ); + } else { // StreamVersion 4-6 + Error = ReadHeaderSV6 ( fp ); + } + + ReadTags(fp); + + simple.PCMSamples = 1152 * simple.Frames - 576; // estimation, exact value needs too much time + if ( simple.PCMSamples > 0 ) + simple.AverageBitrate = (simple.TagOffset - simple.HeaderPosition) * 8. * simple.SampleFreq / simple.PCMSamples; + else + simple.AverageBitrate = 0; + + return Error; +} + +/* end of in_mpc.c */ diff --git a/src/add-ons/media/plugins/musepack/mpc/in_mpc.h b/src/add-ons/media/plugins/musepack/mpc/in_mpc.h new file mode 100644 index 0000000000..b88fde275e --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/in_mpc.h @@ -0,0 +1,111 @@ +#ifndef _in_mpc_h_ +#define _in_mpc_h_ + +#include +#include + +#include "idtag.h" + +class BPositionIO; + +/************************ DEFINES *************************/ +#define VERSION "0.97f" + +// error codes +#define ERROR_CODE_OK 0 +#define ERROR_CODE_FILE -1 +#define ERROR_CODE_SV7BETA 1 +#define ERROR_CODE_CBR 2 +#define ERROR_CODE_IS 3 +#define ERROR_CODE_BLOCKSIZE 4 +#define ERROR_CODE_INVALIDSV 5 + +/************************ TYPEDEF *************************/ +typedef struct { + char* Item; // Name of item (ASCII) + char* Value; // Value of item (UTF-8) + unsigned int Flags; // Flags + size_t ItemSize; // Length of name (bytes) + size_t ValueSize; // Length of value (bytes) + enum tag_rel Reliability; // Reliability of information +} TagItem; + +class StreamInfo { +private: + char *filename; + +public: // ahem fixme + typedef long off_t; + + typedef struct { + double SampleFreq; + unsigned int Channels; + off_t HeaderPosition; // byte position of header + unsigned int StreamVersion; // Streamversion of current file + unsigned int Bitrate; // bitrate of current file (bps) + double AverageBitrate; // Average bitrate in bits/sec + unsigned int Frames; // number of frames contained + int64 PCMSamples; + unsigned int MaxBand; // maximum band-index used (0...31) + unsigned int IS; // Intensity Stereo (0: off, 1: on) + unsigned int MS; // Mid/Side Stereo (0: off, 1: on) + unsigned int BlockSize; // only needed for SV4...SV6 -> not supported + unsigned int Profile; // quality profile + const char* ProfileName; + + // ReplayGain related data + short GainTitle; + short GainAlbum; + unsigned short PeakAlbum; + unsigned short PeakTitle; + + // true gapless stuff + unsigned int IsTrueGapless; // is true gapless used? + unsigned int LastFrameSamples; // number of valid samples within last frame + + unsigned int EncoderVersion; // version of encoder used + char Encoder[256]; + + off_t TagOffset; + off_t TotalFileLength; + } BasicData; + + BasicData simple; + size_t tagitem_count; + TagItem* tagitems; + enum tag_t tagtype; + +public: + StreamInfo (); + ~StreamInfo () { Clear (); } + void SetFilename ( const char * ); + const char *GetFilename (); + void Clear (); + int ReadStreamInfo (BPositionIO *stream); + +private: + //fixme: add writetag here too + int ReadHeaderSV6 ( BPositionIO *file ); + int ReadHeaderSV7 ( BPositionIO *file ); + int ReadHeaderSV8 ( BPositionIO *file ); + int ReadTags ( BPositionIO *file ); // reads all tags from file + int ReadID3v1Tag ( BPositionIO *file ); // reads ID3v1 tag + int ReadAPE1Tag ( BPositionIO *file ); // reads APE 1.0 tag + int ReadAPE2Tag ( BPositionIO *file ); // reads APE 2.0 tag +}; + +typedef struct { + int EQbyMPC; + int EQdB; + unsigned int UpdateBitrate; // 0 = average, >0 average over such a number of frames + int MaxBrokenFrames; + int SkipTrackOnError; + int ReplayGainMode; + int ReplayGainHeadroom; + int DitherUsed; +} SettingsMPC; + +/************************ GLOBALS *************************/ +//extern SettingsMPC PluginSettings; + +#endif diff --git a/src/add-ons/media/plugins/musepack/mpc/minimax.h b/src/add-ons/media/plugins/musepack/mpc/minimax.h new file mode 100644 index 0000000000..c94798e1fc --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/minimax.h @@ -0,0 +1,45 @@ +#ifndef MPP_MINIMAX_H +#define MPP_MINIMAX_H + +#if defined __GNUC__ && defined __cplusplus + +# define maxi(A,B) ( (A) >? (B) ) +# define mini(A,B) ( (A) ? (B) ) +# define mind(A,B) ( (A) ? (B) ) +# define minf(A,B) ( (A) (B) ? (A) : (B) ) +# define mini(A,B) ( (A) < (B) ? (A) : (B) ) +# define maxd(A,B) ( (A) > (B) ? (A) : (B) ) +# define mind(A,B) ( (A) < (B) ? (A) : (B) ) +# define maxf(A,B) ( (A) > (B) ? (A) : (B) ) +# define minf(A,B) ( (A) < (B) ? (A) : (B) ) + +# define absi(A) abs (A) +# define absf(A) fabsf (A) +# define absd(A) fabs (A) + +#else + +# define maxi(A,B) ( (A) > (B) ? (A) : (B) ) +# define mini(A,B) ( (A) < (B) ? (A) : (B) ) +# define maxd(A,B) ( (A) > (B) ? (A) : (B) ) +# define mind(A,B) ( (A) < (B) ? (A) : (B) ) +# define maxf(A,B) ( (A) > (B) ? (A) : (B) ) +# define minf(A,B) ( (A) < (B) ? (A) : (B) ) + +# define absi(A) ( (A) >= 0 ? (A) : -(A) ) +# define absf(A) ( (A) >= 0.f ? (A) : -(A) ) +# define absd(A) ( (A) >= 0. ? (A) : -(A) ) + +#endif /* GNUC && C++ */ + +#endif /* MPP_MINIMAX_H */ diff --git a/src/add-ons/media/plugins/musepack/mpc/mpc_dec.cpp b/src/add-ons/media/plugins/musepack/mpc/mpc_dec.cpp new file mode 100644 index 0000000000..fa860ca415 --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/mpc_dec.cpp @@ -0,0 +1,1259 @@ + +// Klemm settings +#define OTHER_SEEK + +#include +#include +#include +#include +#include "minimax.h" +#include "mpc_dec.h" +#include "requant.h" +#include "huffsv46.h" +#include "huffsv7.h" +#include "synth_filter.h" +#include "bitstream.h" +#include "in_mpc.h" + +#ifndef M_PI +# define M_PI 3.141592653589793238462643383276 +#endif + +//#include "..\cnv_mpc.h" + +void +MPC_decoder::RESET_Synthesis ( void ) +{ + Reset_V (); +} + +void +MPC_decoder::RESET_Y ( void ) +{ + memset ( Y_L, 0, sizeof Y_L ); + memset ( Y_R, 0, sizeof Y_R ); +} + +void +MPC_decoder::RESET_Globals ( void ) +{ + Reset_BitstreamDecode (); + + DecodedFrames = 0; + LastFrame = 0; + LastBitsRead = 0; + StreamVersion = 0; + MS_used = 0; + clips = 0; + SectionBitrate = 0; + NumberOfConsecutiveBrokenFrames = 0; + + memset ( Y_L , 0, sizeof Y_L ); + memset ( Y_R , 0, sizeof Y_R ); + memset ( SCF_Index_L , 0, sizeof SCF_Index_L ); + memset ( SCF_Index_R , 0, sizeof SCF_Index_R ); + memset ( Res_L , 0, sizeof Res_L ); + memset ( Res_R , 0, sizeof Res_R ); + memset ( SCFI_L , 0, sizeof SCFI_L ); + memset ( SCFI_R , 0, sizeof SCFI_R ); + memset ( DSCF_Flag_L , 0, sizeof DSCF_Flag_L ); + memset ( DSCF_Flag_R , 0, sizeof DSCF_Flag_R ); + memset ( DSCF_Reference_L, 0, sizeof DSCF_Reference_L ); + memset ( DSCF_Reference_R, 0, sizeof DSCF_Reference_R ); + memset ( Q , 0, sizeof Q ); + memset ( MS_Flag , 0, sizeof MS_Flag ); +} + +void +MPC_decoder::perform_EQ ( void ) +{ +#if 0 + /*static*/ float SAVE_L [DELAY] [32]; // buffer for ... + /*static*/ float SAVE_R [DELAY] [32]; // ... upper subbands + /*static*/ float FirSave_L [FIR_BANDS] [EQ_TAP]; // buffer for ... + /*static*/ float FirSave_R [FIR_BANDS] [EQ_TAP]; // ... lowest subbands +#endif + float lowestSB_L [FIR_BANDS] [36]; + float lowestSB_R [FIR_BANDS] [36]; + float SWAP [DELAY] [32]; + int n; + int k; + int i; + float tmp; + + for ( i = 0; i < FIR_BANDS; i++ ) // L: delay subbands (synchronize FIR-filtered and gained subbands-samples) + for ( k = 0; k < 36; k++ ) + lowestSB_L [i] [k] = Y_L [k] [i]; + + memcpy ( SWAP, SAVE_L, DELAY * 32 * sizeof(float) ); + memcpy ( SAVE_L, Y_L+36-DELAY, DELAY * 32 * sizeof(float) ); + memmove ( Y_L+DELAY, Y_L, (36 - DELAY) * 32 * sizeof(float) ); + memcpy ( Y_L, SWAP, DELAY * 32 * sizeof(float) ); + + for ( i = 0; i < FIR_BANDS; i++ ) // R: delay subbands (synchronize FIR-filtered and gained subbands-samples) + for ( k = 0; k < 36; k++ ) + lowestSB_R [i] [k] = Y_R [k] [i]; + + memcpy ( SWAP, SAVE_R, DELAY * 32 * sizeof(float) ); + memcpy ( SAVE_R, Y_R+36-DELAY, DELAY * 32 * sizeof(float) ); + memmove ( Y_R+DELAY, Y_R, (36 - DELAY) * 32 * sizeof(float) ); + memcpy ( Y_R, SWAP, DELAY * 32 * sizeof(float) ); + + for ( k = 0; k < 36; k++ ) { // apply global EQ to upper subbands + for ( n = FIR_BANDS; n <= Max_Band; n++ ) { + Y_L [k] [n] *= EQ_gain [n-FIR_BANDS]; + Y_R [k] [n] *= EQ_gain [n-FIR_BANDS]; + } + } + + for ( i = 0; i < FIR_BANDS; i++ ) { // apply FIR to lower subbands for each channel + for ( k = 0; k < EQ_TAP; k++ ) { // L: perform filter for lowest subbands + tmp = 0.; + for ( n = 0; n < EQ_TAP - k; n++ ) + tmp += FirSave_L [i] [k+n] * EQ_Filter [i] [n]; + for ( ; n < EQ_TAP; n++ ) + tmp += lowestSB_L [i] [k+n-EQ_TAP] * EQ_Filter [i] [n]; + Y_L [k] [i] = tmp; + } + for ( ; k < 36; k++ ) { // L: perform filter for lowest subbands + tmp = 0.; + for ( n = 0; n < EQ_TAP; n++ ) + tmp += lowestSB_L [i] [k+n-EQ_TAP] * EQ_Filter [i] [n]; + Y_L [k] [i] = tmp; + } + for ( n = 0; n < EQ_TAP; n++ ) + FirSave_L [i] [n] = lowestSB_L [i] [36-EQ_TAP+n]; + + for ( k = 0; k < EQ_TAP; k++ ) { // R: perform filter for lowest subbands + tmp = 0.; + for ( n = 0; n < EQ_TAP - k; n++ ) + tmp += FirSave_R [i] [k+n] * EQ_Filter [i] [n]; + for ( ; n < EQ_TAP; n++ ) + tmp += lowestSB_R [i] [k+n-EQ_TAP] * EQ_Filter [i] [n]; + Y_R [k] [i] = tmp; + } + for ( ; k < 36; k++ ) { // R: perform filter for lowest subbands + tmp = 0.; + for ( n = 0; n < EQ_TAP; n++ ) + tmp += lowestSB_R [i] [k+n-EQ_TAP] * EQ_Filter [i] [n]; + Y_R [k] [i] = tmp; + } + for ( n = 0; n < EQ_TAP; n++ ) + FirSave_R [i] [n] = lowestSB_R [i] [36-EQ_TAP+n]; + } + + return; +} + +int +MPC_decoder::DECODE ( MPC_SAMPLE_FORMAT *buffer ) +{ + unsigned int FrameBitCnt = 0; + + if ( DecodedFrames >= OverallFrames ) + return 0; // end of file -> abort decoding + + // read jump-info for validity check of frame + FwdJumpInfo = Bitstream_read (20); + SeekTable [DecodedFrames] = 20 + FwdJumpInfo; // ... + + ActDecodePos = (Zaehler << 5) + pos; + + // decode data and check for validity of frame + FrameBitCnt = BitsRead (); + switch ( StreamVersion ) { + case 0x04: + case 0x05: + case 0x06: + Lese_Bitstrom_SV6 (); + break; + case 0x07: + case 0x17: + Lese_Bitstrom_SV7 (); + break; + default: + return 0; + } + FrameWasValid = BitsRead() - FrameBitCnt == FwdJumpInfo; + + // synthesize signal + Requantisierung ( Max_Band ); + //if ( EQ_activated && PluginSettings.EQbyMPC ) + // perform_EQ (); +#if MPC_DECODE == TO_FLOAT + + Synthese_Filter_float ( buffer ); + +#elif MPC_DECODE == TO_PCM + +#if 0 + if ( cfg_dither /*PluginSettings.DitherUsed*/ ) + Synthese_Filter_dithered ( (short*)buffer ); + else + Synthese_Filter_opt ( (short*)buffer ); +#endif + Synthese_Filter_dithered ( buffer ); + +#endif + // (PluginSettings.DitherUsed ? this->Synthese_Filter_dithered : this->Synthese_Filter_opt) ( (short*)buffer ); + + DecodedFrames += 1; + + // cut off first SYNTH_DELAY zero-samples + if ( DecodedFrames == 0 + 1 ) { + //memmove ( buffer, buffer + SYNTH_DELAY * 4, (FRAMELEN - SYNTH_DELAY) * 4 ); + //return (FRAMELEN - 481) * 4; + + //memmove ( buffer, buffer + SYNTH_DELAY * 2, (FRAMELEN - SYNTH_DELAY) * 4*2 ); + memmove ( buffer, buffer + SYNTH_DELAY * 2, (FRAMELEN - SYNTH_DELAY) * 2 * sizeof (MPC_SAMPLE_FORMAT) ); + return (FRAMELEN - 481) * 2; + } + else if ( DecodedFrames == OverallFrames && StreamVersion >= 6 ) + { // reconstruct exact filelength + int mod_block = Bitstream_read (11); + int FilterDecay; + + if (mod_block == 0) mod_block = 1152; // Encoder bugfix + FilterDecay = (mod_block + SYNTH_DELAY) % FRAMELEN; + + // additional FilterDecay samples are needed for decay of synthesis filter + if ( SYNTH_DELAY + mod_block >= FRAMELEN ) { + + // ********************************************************************** + // Rhoades 4/16/2002 + // Commented out are blocks of code which cause gapless playback to fail. + // Temporary fix... + // ********************************************************************** + + if ( ! TrueGaplessPresent ) { + RESET_Y (); + } else { + //if ( FRAMELEN != LastValidSamples ) { + Bitstream_read (20); + Lese_Bitstrom_SV7 (); + Requantisierung ( Max_Band ); + //FilterDecay = LastValidSamples; + //} + //else { + //FilterDecay = 0; + //} + } + //if ( EQ_activated && PluginSettings.EQbyMPC ) + // perform_EQ (); +#if MPC_DECODE == TO_FLOAT + + Synthese_Filter_float ( buffer + 2304 ); + +#elif MPC_DECODE == TO_PCM + +#if 0 + if ( cfg_dither /*PluginSettings.DitherUsed*/ ) + Synthese_Filter_dithered ( (short*)buffer + 2304 ); + else + Synthese_Filter_opt ( (short*)buffer + 2304 ); +#endif + Synthese_Filter_dithered ( buffer + 2304 ); + +#endif + // (PluginSettings.DitherUsed ? this->Synthese_Filter_dithered : this->Synthese_Filter_opt) ( (short*)buffer + 2304); + // return (FRAMELEN + FilterDecay) * 4; + return (FRAMELEN + FilterDecay) * 2; + } + else { // there are only FilterDecay samples needed for this frame + // return FilterDecay * 4; + return FilterDecay * 2; + } + } + else { // full frame + // return FRAMELEN * 4; + return FRAMELEN * 2; + } +} + +void +MPC_decoder::Requantisierung ( const int Last_Band ) +{ + int Band; + int n; + float facL; + float facR; + float templ; + float tempr; + float* YL; + float* YR; + int* L; + int* R; + + // requantization and scaling of subband-samples + for ( Band = 0; Band <= Last_Band; Band++ ) { // setting pointers + YL = Y_L [0] + Band; + YR = Y_R [0] + Band; + L = Q [Band].L; + R = Q [Band].R; + /************************** MS-coded **************************/ + if ( MS_Flag [Band] ) { + if ( Res_L [Band] ) { + if ( Res_R [Band] ) { // M!=0, S!=0 + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][0]]; + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][0]]; + for ( n = 0; n < 12; n++, YL += 32, YR += 32 ) { + *YL = (templ = *L++ * facL)+(tempr = *R++ * facR); + *YR = templ - tempr; + } + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][1]]; + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][1]]; + for ( ; n < 24; n++, YL += 32, YR += 32 ) { + *YL = (templ = *L++ * facL)+(tempr = *R++ * facR); + *YR = templ - tempr; + } + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][2]]; + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][2]]; + for ( ; n < 36; n++, YL += 32, YR += 32 ) { + *YL = (templ = *L++ * facL)+(tempr = *R++ * facR); + *YR = templ - tempr; + } + } else { // M!=0, S==0 + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][0]]; + for ( n = 0; n < 12; n++, YL += 32, YR += 32 ) { + *YR = *YL = *L++ * facL; + } + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][1]]; + for ( ; n < 24; n++, YL += 32, YR += 32 ) { + *YR = *YL = *L++ * facL; + } + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][2]]; + for ( ; n < 36; n++, YL += 32, YR += 32 ) { + *YR = *YL = *L++ * facL; + } + } + } else { + if (Res_R[Band]) // M==0, S!=0 + { + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][0]]; + for ( n = 0; n < 12; n++, YL += 32, YR += 32 ) { + *YR = - (*YL = *(R++) * facR); + } + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][1]]; + for ( ; n < 24; n++, YL += 32, YR += 32 ) { + *YR = - (*YL = *(R++) * facR); + } + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][2]]; + for ( ; n < 36; n++, YL += 32, YR += 32 ) { + *YR = - (*YL = *(R++) * facR); + } + } else { // M==0, S==0 + for ( n = 0; n < 36; n++, YL += 32, YR += 32 ) { + *YR = *YL = 0.f; + } + } + } + } + /************************** LR-coded **************************/ + else { + if ( Res_L [Band] ) { + if ( Res_R [Band] ) { // L!=0, R!=0 + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][0]]; + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][0]]; + for (n = 0; n < 12; n++, YL += 32, YR += 32 ) { + *YL = *L++ * facL; + *YR = *R++ * facR; + } + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][1]]; + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][1]]; + for (; n < 24; n++, YL += 32, YR += 32 ) { + *YL = *L++ * facL; + *YR = *R++ * facR; + } + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][2]]; + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][2]]; + for (; n < 36; n++, YL += 32, YR += 32 ) { + *YL = *L++ * facL; + *YR = *R++ * facR; + } + } else { // L!=0, R==0 + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][0]]; + for ( n = 0; n < 12; n++, YL += 32, YR += 32 ) { + *YL = *L++ * facL; + *YR = 0.f; + } + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][1]]; + for ( ; n < 24; n++, YL += 32, YR += 32 ) { + *YL = *L++ * facL; + *YR = 0.f; + } + facL = Cc[Res_L[Band]] * SCF[(unsigned char)SCF_Index_L[Band][2]]; + for ( ; n < 36; n++, YL += 32, YR += 32 ) { + *YL = *L++ * facL; + *YR = 0.f; + } + } + } + else { + if ( Res_R [Band] ) { // L==0, R!=0 + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][0]]; + for ( n = 0; n < 12; n++, YL += 32, YR += 32 ) { + *YL = 0.f; + *YR = *R++ * facR; + } + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][1]]; + for ( ; n < 24; n++, YL += 32, YR += 32 ) { + *YL = 0.f; + *YR = *R++ * facR; + } + facR = Cc[Res_R[Band]] * SCF[(unsigned char)SCF_Index_R[Band][2]]; + for ( ; n < 36; n++, YL += 32, YR += 32 ) { + *YL = 0.f; + *YR = *R++ * facR; + } + } else { // L==0, R==0 + for ( n = 0; n < 36; n++, YL += 32, YR += 32 ) { + *YR = *YL = 0.f; + } + } + } + } + } +} + +/****************************************** SV 6 ******************************************/ +void +MPC_decoder::Lese_Bitstrom_SV6 ( void ) +{ + int n,k; + int Max_used_Band=0; + HuffmanTyp *Table; + const HuffmanTyp *x1; + const HuffmanTyp *x2; + int *L; + int *R; + int *ResL = Res_L; + int *ResR = Res_R; + + /************************ HEADER **************************/ + ResL = Res_L; + ResR = Res_R; + for (n=0; n<=Max_Band; ++n, ++ResL, ++ResR) + { + if (n<11) Table = Region_A; + else if (n>=11 && n<=22) Table = Region_B; + else /*if (n>=23)*/ Table = Region_C; + + *ResL = Q_res[n][Huffman_Decode(Table)]; + if (MS_used) MS_Flag[n] = Bitstream_read(1); + *ResR = Q_res[n][Huffman_Decode(Table)]; + + // only perform the following procedure up to the maximum non-zero subband + if (*ResL || *ResR) Max_used_Band = n; + } + + /************************* SCFI-Bundle *****************************/ + ResL = Res_L; + ResR = Res_R; + for (n=0; n<=Max_used_Band; ++n, ++ResL, ++ResR) { + if (*ResL) SCFI_Bundle_read(SCFI_Bundle, &SCFI_L[n], &DSCF_Flag_L[n]); + if (*ResR) SCFI_Bundle_read(SCFI_Bundle, &SCFI_R[n], &DSCF_Flag_R[n]); + } + + /***************************** SCFI ********************************/ + ResL = Res_L; + ResR = Res_R; + L = SCF_Index_L[0]; + R = SCF_Index_R[0]; + for (n=0; n<=Max_used_Band; ++n, ++ResL, ++ResR, L+=3, R+=3) + { + if (*ResL) + { + /*********** DSCF ************/ + if (DSCF_Flag_L[n]==1) + { + L[2] = DSCF_Reference_L[n]; + switch (SCFI_L[n]) + { + case 3: + L[0] = L[2] + Huffman_Decode_fast(DSCF_Entropie); + L[1] = L[0]; + L[2] = L[1]; + break; + case 1: + L[0] = L[2] + Huffman_Decode_fast(DSCF_Entropie); + L[1] = L[0] + Huffman_Decode_fast(DSCF_Entropie); + L[2] = L[1]; + break; + case 2: + L[0] = L[2] + Huffman_Decode_fast(DSCF_Entropie); + L[1] = L[0]; + L[2] = L[1] + Huffman_Decode_fast(DSCF_Entropie); + break; + case 0: + L[0] = L[2] + Huffman_Decode_fast(DSCF_Entropie); + L[1] = L[0] + Huffman_Decode_fast(DSCF_Entropie); + L[2] = L[1] + Huffman_Decode_fast(DSCF_Entropie); + break; + default: + return; + break; + } + } + /************ SCF ************/ + else + { + switch (SCFI_L[n]) + { + case 3: + L[0] = Bitstream_read(6); + L[1] = L[0]; + L[2] = L[1]; + break; + case 1: + L[0] = Bitstream_read(6); + L[1] = Bitstream_read(6); + L[2] = L[1]; + break; + case 2: + L[0] = Bitstream_read(6); + L[1] = L[0]; + L[2] = Bitstream_read(6); + break; + case 0: + L[0] = Bitstream_read(6); + L[1] = Bitstream_read(6); + L[2] = Bitstream_read(6); + break; + default: + return; + break; + } + } + // update Reference for DSCF + DSCF_Reference_L[n] = L[2]; + } + if (*ResR) + { + R[2] = DSCF_Reference_R[n]; + /*********** DSCF ************/ + if (DSCF_Flag_R[n]==1) + { + switch (SCFI_R[n]) + { + case 3: + R[0] = R[2] + Huffman_Decode_fast(DSCF_Entropie); + R[1] = R[0]; + R[2] = R[1]; + break; + case 1: + R[0] = R[2] + Huffman_Decode_fast(DSCF_Entropie); + R[1] = R[0] + Huffman_Decode_fast(DSCF_Entropie); + R[2] = R[1]; + break; + case 2: + R[0] = R[2] + Huffman_Decode_fast(DSCF_Entropie); + R[1] = R[0]; + R[2] = R[1] + Huffman_Decode_fast(DSCF_Entropie); + break; + case 0: + R[0] = R[2] + Huffman_Decode_fast(DSCF_Entropie); + R[1] = R[0] + Huffman_Decode_fast(DSCF_Entropie); + R[2] = R[1] + Huffman_Decode_fast(DSCF_Entropie); + break; + default: + return; + break; + } + } + /************ SCF ************/ + else + { + switch (SCFI_R[n]) + { + case 3: + R[0] = Bitstream_read(6); + R[1] = R[0]; + R[2] = R[1]; + break; + case 1: + R[0] = Bitstream_read(6); + R[1] = Bitstream_read(6); + R[2] = R[1]; + break; + case 2: + R[0] = Bitstream_read(6); + R[1] = R[0]; + R[2] = Bitstream_read(6); + break; + case 0: + R[0] = Bitstream_read(6); + R[1] = Bitstream_read(6); + R[2] = Bitstream_read(6); + break; + default: + return; + break; + } + } + // update Reference for DSCF + DSCF_Reference_R[n] = R[2]; + } + } + + /**************************** Samples ****************************/ + ResL = Res_L; + ResR = Res_R; + for (n=0; n<=Max_used_Band; ++n, ++ResL, ++ResR) + { + // setting pointers + x1 = SampleHuff[*ResL]; + x2 = SampleHuff[*ResR]; + L = Q[n].L; + R = Q[n].R; + + if (x1!=NULL || x2!=NULL) + for (k=0; k<36; ++k) + { + if (x1 != NULL) *L++ = Huffman_Decode_fast (x1); + if (x2 != NULL) *R++ = Huffman_Decode_fast (x2); + } + + if (*ResL>7 || *ResR>7) + for (k=0; k<36; ++k) + { + if (*ResL>7) *L++ = (int)Bitstream_read(Res_bit[*ResL]) - Dc[*ResL]; + if (*ResR>7) *R++ = (int)Bitstream_read(Res_bit[*ResR]) - Dc[*ResR]; + } + } +} + +/****************************************** SV 7 ******************************************/ +void +MPC_decoder::Lese_Bitstrom_SV7 ( void ) +{ + // these arrays hold decoding results for bundled quantizers (3- and 5-step) + /*static*/ int idx30[] = { -1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1}; + /*static*/ int idx31[] = { -1,-1,-1, 0, 0, 0, 1, 1, 1,-1,-1,-1, 0, 0, 0, 1, 1, 1,-1,-1,-1, 0, 0, 0, 1, 1, 1}; + /*static*/ int idx32[] = { -1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + /*static*/ int idx50[] = { -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; + /*static*/ int idx51[] = { -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2}; + + int n,k; + int Max_used_Band=0; + const HuffmanTyp *Table; + int idx; + int *L ,*R; + int *ResL,*ResR; + unsigned int tmp; + + /***************************** Header *****************************/ + ResL = Res_L; + ResR = Res_R; + + // first subband + *ResL = Bitstream_read(4); + *ResR = Bitstream_read(4); + if (MS_used && !(*ResL==0 && *ResR==0)) MS_Flag[0] = Bitstream_read(1); + + // consecutive subbands + ++ResL; ++ResR; // increase pointers + for (n=1; n<=Max_Band; ++n, ++ResL, ++ResR) + { + idx = Huffman_Decode_fast(HuffHdr); + *ResL = (idx!=4) ? *(ResL-1) + idx : Bitstream_read(4); + + idx = Huffman_Decode_fast(HuffHdr); + *ResR = (idx!=4) ? *(ResR-1) + idx : Bitstream_read(4); + + if (MS_used && !(*ResL==0 && *ResR==0)) MS_Flag[n] = Bitstream_read(1); + + // only perform following procedures up to the maximum non-zero subband + if (*ResL!=0 || *ResR!=0) Max_used_Band = n; + } + /****************************** SCFI ******************************/ + L = SCFI_L; + R = SCFI_R; + ResL = Res_L; + ResR = Res_R; + for (n=0; n<=Max_used_Band; ++n, ++L, ++R, ++ResL, ++ResR) { + if (*ResL) *L = Huffman_Decode_faster(HuffSCFI); + if (*ResR) *R = Huffman_Decode_faster(HuffSCFI); + } + + /**************************** SCF/DSCF ****************************/ + ResL = Res_L; + ResR = Res_R; + L = SCF_Index_L[0]; + R = SCF_Index_R[0]; + for (n=0; n<=Max_used_Band; ++n, ++ResL, ++ResR, L+=3, R+=3) { + if (*ResL) + { + L[2] = DSCF_Reference_L[n]; + switch (SCFI_L[n]) + { + case 1: + idx = Huffman_Decode_fast(HuffDSCF); + L[0] = (idx!=8) ? L[2] + idx : Bitstream_read(6); + idx = Huffman_Decode_fast(HuffDSCF); + L[1] = (idx!=8) ? L[0] + idx : Bitstream_read(6); + L[2] = L[1]; + break; + case 3: + idx = Huffman_Decode_fast(HuffDSCF); + L[0] = (idx!=8) ? L[2] + idx : Bitstream_read(6); + L[1] = L[0]; + L[2] = L[1]; + break; + case 2: + idx = Huffman_Decode_fast(HuffDSCF); + L[0] = (idx!=8) ? L[2] + idx : Bitstream_read(6); + L[1] = L[0]; + idx = Huffman_Decode_fast(HuffDSCF); + L[2] = (idx!=8) ? L[1] + idx : Bitstream_read(6); + break; + case 0: + idx = Huffman_Decode_fast(HuffDSCF); + L[0] = (idx!=8) ? L[2] + idx : Bitstream_read(6); + idx = Huffman_Decode_fast(HuffDSCF); + L[1] = (idx!=8) ? L[0] + idx : Bitstream_read(6); + idx = Huffman_Decode_fast(HuffDSCF); + L[2] = (idx!=8) ? L[1] + idx : Bitstream_read(6); + break; + default: + return; + break; + } + // update Reference for DSCF + DSCF_Reference_L[n] = L[2]; + } + if (*ResR) + { + R[2] = DSCF_Reference_R[n]; + switch (SCFI_R[n]) + { + case 1: + idx = Huffman_Decode_fast(HuffDSCF); + R[0] = (idx!=8) ? R[2] + idx : Bitstream_read(6); + idx = Huffman_Decode_fast(HuffDSCF); + R[1] = (idx!=8) ? R[0] + idx : Bitstream_read(6); + R[2] = R[1]; + break; + case 3: + idx = Huffman_Decode_fast(HuffDSCF); + R[0] = (idx!=8) ? R[2] + idx : Bitstream_read(6); + R[1] = R[0]; + R[2] = R[1]; + break; + case 2: + idx = Huffman_Decode_fast(HuffDSCF); + R[0] = (idx!=8) ? R[2] + idx : Bitstream_read(6); + R[1] = R[0]; + idx = Huffman_Decode_fast(HuffDSCF); + R[2] = (idx!=8) ? R[1] + idx : Bitstream_read(6); + break; + case 0: + idx = Huffman_Decode_fast(HuffDSCF); + R[0] = (idx!=8) ? R[2] + idx : Bitstream_read(6); + idx = Huffman_Decode_fast(HuffDSCF); + R[1] = (idx!=8) ? R[0] + idx : Bitstream_read(6); + idx = Huffman_Decode_fast(HuffDSCF); + R[2] = (idx!=8) ? R[1] + idx : Bitstream_read(6); + break; + default: + return; + break; + } + // update Reference for DSCF + DSCF_Reference_R[n] = R[2]; + } + } + /***************************** Samples ****************************/ + ResL = Res_L; + ResR = Res_R; + L = Q[0].L; + R = Q[0].R; + for (n=0; n<=Max_used_Band; ++n, ++ResL, ++ResR, L+=36, R+=36) + { + /************** links **************/ + switch (*ResL) + { + case -2: case -3: case -4: case -5: case -6: case -7: case -8: case -9: + case -10: case -11: case -12: case -13: case -14: case -15: case -16: case -17: + L += 36; + break; + case -1: + for (k=0; k<36; k++ ) { + tmp = random_int (); + *L++ = ((tmp >> 24) & 0xFF) + ((tmp >> 16) & 0xFF) + ((tmp >> 8) & 0xFF) + ((tmp >> 0) & 0xFF) - 510; + } + break; + case 0: + L += 36;// increase pointer + break; + case 1: + Table = HuffQ[Bitstream_read(1)][1]; + for (k=0; k<12; ++k) + { + idx = Huffman_Decode_fast(Table); + *L++ = idx30[idx]; + *L++ = idx31[idx]; + *L++ = idx32[idx]; + } + break; + case 2: + Table = HuffQ[Bitstream_read(1)][2]; + for (k=0; k<18; ++k) + { + idx = Huffman_Decode_fast(Table); + *L++ = idx50[idx]; + *L++ = idx51[idx]; + } + break; + case 3: + case 4: + Table = HuffQ[Bitstream_read(1)][*ResL]; + for (k=0; k<36; ++k) + *L++ = Huffman_Decode_faster(Table); + break; + case 5: + Table = HuffQ[Bitstream_read(1)][*ResL]; + for (k=0; k<36; ++k) + *L++ = Huffman_Decode_fast(Table); + break; + case 6: + case 7: + Table = HuffQ[Bitstream_read(1)][*ResL]; + for (k=0; k<36; ++k) + *L++ = Huffman_Decode(Table); + break; + case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: + tmp = Dc[*ResL]; + for (k=0; k<36; ++k) + *L++ = (int)Bitstream_read(Res_bit[*ResL]) - tmp; + break; + default: + return; + } + /************** rechts **************/ + switch (*ResR) + { + case -2: case -3: case -4: case -5: case -6: case -7: case -8: case -9: + case -10: case -11: case -12: case -13: case -14: case -15: case -16: case -17: + R += 36; + break; + case -1: + for (k=0; k<36; k++ ) { + tmp = random_int (); + *R++ = ((tmp >> 24) & 0xFF) + ((tmp >> 16) & 0xFF) + ((tmp >> 8) & 0xFF) + ((tmp >> 0) & 0xFF) - 510; + } + break; + case 0: + R += 36;// increase pointer + break; + case 1: + Table = HuffQ[Bitstream_read(1)][1]; + for (k=0; k<12; ++k) + { + idx = Huffman_Decode_fast(Table); + *R++ = idx30[idx]; + *R++ = idx31[idx]; + *R++ = idx32[idx]; + } + break; + case 2: + Table = HuffQ[Bitstream_read(1)][2]; + for (k=0; k<18; ++k) + { + idx = Huffman_Decode_fast(Table); + *R++ = idx50[idx]; + *R++ = idx51[idx]; + } + break; + case 3: + case 4: + Table = HuffQ[Bitstream_read(1)][*ResR]; + for (k=0; k<36; ++k) + *R++ = Huffman_Decode_faster(Table); + break; + case 5: + Table = HuffQ[Bitstream_read(1)][*ResR]; + for (k=0; k<36; ++k) + *R++ = Huffman_Decode_fast(Table); + break; + case 6: + case 7: + Table = HuffQ[Bitstream_read(1)][*ResR]; + for (k=0; k<36; ++k) + *R++ = Huffman_Decode(Table); + break; + case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: + tmp = Dc[*ResR]; + for (k=0; k<36; ++k) + *R++ = (int)Bitstream_read(Res_bit[*ResR]) - tmp; + break; + default: + return; + } + } +} + +MPC_decoder::~MPC_decoder () +{ + free ( SeekTable ); + //if ( m_reader ) delete m_reader; + // ^^ breaks wa3 +} + +MPC_decoder::MPC_decoder ( Reader *r ) +{ + m_reader = r; + + HuffQ[0][0] = 0; + HuffQ[1][0] = 0; + HuffQ[0][1] = HuffQ1[0]; + HuffQ[1][1] = HuffQ1[1]; + HuffQ[0][2] = HuffQ2[0]; + HuffQ[1][2] = HuffQ2[1]; + HuffQ[0][3] = HuffQ3[0]; + HuffQ[1][3] = HuffQ3[1]; + HuffQ[0][4] = HuffQ4[0]; + HuffQ[1][4] = HuffQ4[1]; + HuffQ[0][5] = HuffQ5[0]; + HuffQ[1][5] = HuffQ5[1]; + HuffQ[0][6] = HuffQ6[0]; + HuffQ[1][6] = HuffQ6[1]; + HuffQ[0][7] = HuffQ7[0]; + HuffQ[1][7] = HuffQ7[1]; + + SampleHuff[0] = NULL; + SampleHuff[1] = Entropie_1; + SampleHuff[2] = Entropie_2; + SampleHuff[3] = Entropie_3; + SampleHuff[4] = Entropie_4; + SampleHuff[5] = Entropie_5; + SampleHuff[6] = Entropie_6; + SampleHuff[7] = Entropie_7; + SampleHuff[8] = NULL; + SampleHuff[9] = NULL; + SampleHuff[10] = NULL; + SampleHuff[11] = NULL; + SampleHuff[12] = NULL; + SampleHuff[13] = NULL; + SampleHuff[14] = NULL; + SampleHuff[15] = NULL; + SampleHuff[16] = NULL; + SampleHuff[17] = NULL; + + SeekTable = NULL; + EQ_activated = 0; + MPCHeaderPos = 0; + StreamVersion = 0; + MS_used = 0; + FwdJumpInfo = 0; + ActDecodePos = 0; + FrameWasValid = 0; + OverallFrames = 0; + DecodedFrames = 0; + LastFrame = 0; + LastBitsRead = 0; + SectionBitrate = 0; + LastValidSamples = 0; + TrueGaplessPresent = 0; + NumberOfConsecutiveBrokenFrames = 0; + WordsRead = 0; + Max_Band = 0; + SampleRate = 0; + clips = 0; + __r1 = 1; + __r2 = 1; + + dword = 0; + pos = 0; + Zaehler = 0; + WordsRead = 0; + Max_Band = 0; + + memset ( SAVE_L, 0, sizeof (SAVE_L) ); + memset ( SAVE_R, 0, sizeof (SAVE_R) ); + memset ( FirSave_L, 0, sizeof (FirSave_L) ); + memset ( FirSave_R, 0, sizeof (FirSave_R) ); + + initialisiere_Quantisierungstabellen (); + Huffman_SV6_Decoder (); + Huffman_SV7_Decoder (); +} + +void MPC_decoder::SetStreamInfo ( StreamInfo *si ) +{ + StreamVersion = si->simple.StreamVersion; + MS_used = si->simple.MS; + Max_Band = si->simple.MaxBand; + OverallFrames = si->simple.Frames; + MPCHeaderPos = si->simple.HeaderPosition; + LastValidSamples = si->simple.LastFrameSamples; + TrueGaplessPresent = si->simple.IsTrueGapless; + SectionBitrate = (int)si->simple.AverageBitrate; + SampleRate = (int)si->simple.SampleFreq; + + if ( SeekTable != NULL ) free ( SeekTable ); + SeekTable = (unsigned short *)calloc ( sizeof(unsigned short), OverallFrames+64 ); +} + +int MPC_decoder::FileInit () +{ + // AB: setting position to the beginning of the data-bitstream + switch ( StreamVersion ) { + case 0x04: f_seek ( 4 + MPCHeaderPos, SEEK_SET); pos = 16; break; // Geht auch über eine der Helperfunktionen + case 0x05: + case 0x06: f_seek ( 8 + MPCHeaderPos, SEEK_SET); pos = 0; break; + case 0x07: + case 0x17: f_seek ( 24 + MPCHeaderPos, SEEK_SET); pos = 8; break; + default: return 0; + } + + // AB: fill buffer and initialize decoder + f_read ( Speicher, 4*MEMSIZE ); + dword = Speicher [Zaehler = 0]; + + return 1; +} + +//--------------------------------------------------------------- +// will seek from the beginning of the file to the desired +// position in ms (given by seek_needed) +//--------------------------------------------------------------- + +void +MPC_decoder::Helper1 ( unsigned long bitpos ) +{ + f_seek ( (bitpos>>5) * 4 + MPCHeaderPos, SEEK_SET ); + f_read ( Speicher, sizeof(int)*2 ); + dword = Speicher [ Zaehler = 0]; + pos = bitpos & 31; +} + +void +MPC_decoder::Helper2 ( unsigned long bitpos ) +{ + f_seek ( (bitpos>>5) * 4 + MPCHeaderPos, SEEK_SET ); + f_read ( Speicher, sizeof(int) * MEMSIZE ); + dword = Speicher [ Zaehler = 0]; + pos = bitpos & 31; +} + +void +MPC_decoder::Helper3 ( unsigned long bitpos, long* buffoffs ) +{ + pos = bitpos & 31; + bitpos >>= 5; + if ( (unsigned long)(bitpos - *buffoffs) >= MEMSIZE-2 ) { + *buffoffs = bitpos; + f_seek ( bitpos * 4L + MPCHeaderPos, SEEK_SET ); + f_read ( Speicher, sizeof(int)*MEMSIZE ); + } + dword = Speicher [ Zaehler = bitpos - *buffoffs ]; +} + +int +MPC_decoder::perform_jump ( int seek_needed ) +{ + unsigned long fpos; + unsigned int FrameBitCnt; + unsigned int RING; + int fwd; + unsigned int decframes; + unsigned long buffoffs = 0x80000000; + + switch ( StreamVersion ) { // setting position to the beginning of the data-bitstream + case 0x04: fpos = 48; break; + case 0x05: + case 0x06: fpos = 64; break; + case 0x07: + case 0x17: fpos = 200; break; + default : return 0; // was gibt diese Funktion im Falle eines Fehlers zurück ??? + } + + fwd = (int) ( seek_needed * (float)SampleRate * 0.001 / FRAMELEN + .5f ); // no of frames to skip + fwd = fwd < (int)OverallFrames ? fwd : (int)OverallFrames; // prevent from desired position out of allowed range + decframes = DecodedFrames; + DecodedFrames = 0; // reset number of decoded frames + + if ( fwd > 32 && decframes > 128 ) { // only do proceed, if desired position is not in between the first 32 frames + for ( ; (int)DecodedFrames + 32 < fwd; DecodedFrames++ ) { // proceed until 32 frames before (!!) desired position (allows to scan the scalefactors) + if ( SeekTable [DecodedFrames] == 0 ) { +#ifdef OTHER_SEEK + Helper3 ( fpos, (long*)&buffoffs ); +#else + Helper1 ( fpos ); +#endif + fpos += SeekTable [DecodedFrames] = 20 + Bitstream_read (20); // calculate desired pos (in Bits) + } else { + fpos += SeekTable [DecodedFrames]; + } + } + } + Helper2 ( fpos ); + + for ( ; (int)DecodedFrames < fwd; DecodedFrames++ ) { // read the last 32 frames before the desired position to scan the scalefactors (artifactless jumping) + RING = Zaehler; + FwdJumpInfo = Bitstream_read (20); // read jump-info + ActDecodePos = (Zaehler << 5) + pos; + FrameBitCnt = BitsRead (); // scanning the scalefactors and check for validity of frame + if (StreamVersion >= 7) Lese_Bitstrom_SV7 (); + else Lese_Bitstrom_SV6 (); + if ( BitsRead() - FrameBitCnt != FwdJumpInfo ) { +// Box ("Bug in perform_jump"); + return 0; + } + if ( (RING ^ Zaehler) & MEMSIZE2 ) // update buffer + f_read ( Speicher + (RING & MEMSIZE2), 4 * MEMSIZE2 ); + } + + RESET_Synthesis (); // resetting synthesis filter to avoid "clicks" + LastBitsRead = BitsRead (); + LastFrame = DecodedFrames; + + return 1; +} + +void MPC_decoder::UpdateBuffer ( unsigned int RING ) +{ + if ( (RING ^ Zaehler) & MEMSIZE2 ) + f_read ( Speicher + (RING & MEMSIZE2), 4 * MEMSIZE2 ); // update buffer +} + +#if 0 +void +MPC_decoder::EQSet ( int on, char data[10], int preamp ) +{ + /*static*/ const int specline [10] = { 1, 4, 7, 14, 23, 70, 139, 279, 325, 372 }; + /*static*/ const int sym = (EQ_TAP - 1) / 2; + float set [512]; + float x [512]; + float mid [32]; + float power[10]; + float win; + int i; + int n; + int k; + int idx; + + /* + The implemented EQ utilizes the given frequencies and interpolates the power level. + All subbands except the lowest FIR_BANDS subbands will be attenuated by the calculated + average gain. The first FIR_BANDS subbands will be processed by a EQ_TAP-order FIR-filter, + because the frequency resolution of the EQ is much higher than the subbands bandwidth. + */ + EQ_activated = 0; + if ( on ) { + + // calculate desired attenuation + for ( n = 0; n < 10; n++ ) { + power[n] = (31-(int)data[n]) * PluginSettings.EQdB/32.f; + power[n] += (31- preamp) * PluginSettings.EQdB/32.f; + } + + // calculate desired attenuation for each bin + set[0] = power[0]; + for ( k = 1; k < 4; k++ ) set [k]= (power[0]*(4 -k) + power[1]*(k- 1)) / 3.f; + for ( k = 4; k < 7; k++ ) set [k]= (power[1]*(7 -k) + power[2]*(k- 4)) / 3.f; + for ( k = 7; k < 14; k++ ) set [k]= (power[2]*(14 -k) + power[3]*(k- 7)) / 7.f; + for ( k = 14; k < 23; k++ ) set [k]= (power[3]*(23 -k) + power[4]*(k- 14)) / 9.f; + for ( k = 23; k < 70; k++ ) set [k]= (power[4]*(70 -k) + power[5]*(k- 23)) / 47.f; + for ( k = 70; k <139; k++ ) set [k]= (power[5]*(139-k) + power[6]*(k- 70)) / 69.f; + for ( k =139; k <279; k++ ) set [k]= (power[6]*(279-k) + power[7]*(k-139)) /140.f; + for ( k =279; k <325; k++ ) set [k]= (power[7]*(325-k) + power[8]*(k-279)) / 46.f; + for ( k =325; k <372; k++ ) set [k]= (power[8]*(372-k) + power[9]*(k-325)) / 47.f; + for ( k =372; k <512; k++ ) set [k]= power[9]; + + // transform from level to power + for ( k = 0; k < 512; k++ ) + set[k] = (float) pow ( 10., 0.1*set[k] ); + + /************************** gain for upper subbands ****************************/ + // transform to attenuation (gain) per subband + memset ( mid, 0, sizeof(mid) ); + for ( k = 16 * FIR_BANDS; k < 512; k++ ) + mid [k >> 4] += set [k]; // summarize power + for (n=FIR_BANDS ; n<32 ; ++n) + EQ_gain [n - FIR_BANDS] = (float) sqrt (mid[n] / 16.); // average gain + + /************************** FIR for lowest subbands ****************************/ + for ( i = 0; i < FIR_BANDS; i++ ) { // calculate impulse response of FIR via IDFT + for ( n = 0; n < DELAY; n++ ) { + x[n] = 0; + for ( k = 0; k < 16; k++ ) { + idx = i & 1 ? (i<<4)+15-k : (i<<4)+k; // frequency inversion of every second subband + x[n] += (float) ( sqrt (set[idx]) * cos (2*M_PI*n*k/32) ); + } + x[n] /= 16.; + } + // calculate a symmetric EQ_TAP-tap FIR-filter + for ( n = 0; n < EQ_TAP; n++ ) { + win = (float) sin ( (n+1) * M_PI / (EQ_TAP+1) ); + win *= win; // Portable, falls win = sin² () die Absicht sein sollte + EQ_Filter[i][n] = n <= sym ? x[sym-n]*win : x[n-sym]*win; + } + } + EQ_activated = 1; + } + + return; +} +#endif + +//--------------------------------------------------------------- +// calculates the factor that must be applied to match the +// chosen ReplayGain-mode +//--------------------------------------------------------------- +#if 0 +float +MPC_decoder::ProcessReplayGain ( int mode, StreamInfo *info ) +{ + unsigned char modetab [7] = { 0,4,5,6,7,2,3 }; + char message [800]; + float factor_gain; + float factor_clip; + float factor_preamp; + int Gain = 0; + int Peak = 0; + int Headroom = 0; + char* p = message; + + mode = modetab [mode]; + + if ( (mode & 1) == 0 ) + Gain = info->simple.GainTitle, Peak = info->simple.PeakTitle; + else + Gain = info->simple.GainAlbum, Peak = info->simple.PeakAlbum; + + /* + if ( PluginSettings.DebugUsed ) { + p += sprintf ( p, "UsedPeak: %u UsedGain: %+5.2f\n", Peak, 0.01*Gain ); + } + */ + + if ( (mode & 2) == 0 ) + Gain = 0; + + if ( (mode & 4) == 0 ) + Peak = 0; + + if ( mode == 0 ) + Headroom = 0; + else + Headroom = cfg_headroom /*PluginSettings.ReplayGainHeadroom*/ - 14; // K-2...26, 2 => -12, 26 => +12 + + // calculate multipliers for ReplayGain and ClippingPrevention + factor_preamp = (float) pow (10., -0.05 * Headroom); + factor_gain = (float) pow (10., 0.0005 * Gain); + + if ( cfg_clipprotect == FALSE ) { + factor_clip = 1.f; + } else { + factor_clip = (float) (32767./( Peak + 1 ) ); + + if ( factor_preamp * factor_gain < factor_clip ) + factor_clip = 1.f; + else + factor_clip /= factor_preamp * factor_gain; + } + + return factor_preamp * factor_gain * factor_clip; +} +#endif diff --git a/src/add-ons/media/plugins/musepack/mpc/mpc_dec.h b/src/add-ons/media/plugins/musepack/mpc/mpc_dec.h new file mode 100644 index 0000000000..78d06061d2 --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/mpc_dec.h @@ -0,0 +1,238 @@ +#ifndef _mpp_dec_h_ +#define _mpp_dec_h_ + +#include + +#ifndef _in_mpc_h_ +class StreamInfo; +#endif + +#define _inline inline + +#define TO_FLOAT 1 +#define TO_PCM 2 + +#ifndef MPC_DECODE + #define MPC_DECODE TO_FLOAT // decode to 32 bit floats ( -1.000...+1.000 ) +//#define MPC_DECODE TO_PCM // decode to 16 bit PCM ( -32768...+32767 ) +#endif + + +#if MPC_DECODE == TO_FLOAT + #define MPC_SAMPLE_FORMAT float + #define MPC_SAMPLE_BPS 32 + #define MPC_SAMPLE_TYPE "FLOAT" +#elif MPC_DECODE == TO_PCM + #define MPC_SAMPLE_FORMAT short + #define MPC_SAMPLE_BPS 16 + #define MPC_SAMPLE_TYPE "PCM" +#else + #error MPC_DECODE incorrect or undefined. +#endif + + +#define EQ_TAP 13 // length of FIR filter for EQ +#define DELAY ((EQ_TAP + 1) / 2) // delay of FIR +#define FIR_BANDS 4 // number of subbands to be FIR filtered + +#define MEMSIZE 16384 // overall buffer size +#define MEMSIZE2 (MEMSIZE/2) // size of one buffer +#define MEMMASK (MEMSIZE-1) +#define V_MEM 2304 +#define FRAMELEN (36 * 32) // samples per frame +#define SYNTH_DELAY 481 + + +class Reader { +public: + virtual size_t read ( void *ptr, size_t size ) = 0; + virtual size_t write ( void *ptr, size_t size ) = 0; + virtual int seek ( int offset, int origin ) = 0; + virtual long tell () = 0; + virtual void seteof ( size_t ofs ) {}; + virtual ~Reader () {} + virtual int canwrite () { return 0; }; // is writing supported or not +}; + +class MPC_decoder { +private: + Reader *m_reader; + +public: + MPC_decoder ( Reader *r ); + ~MPC_decoder (); + + void SetStreamInfo ( StreamInfo *si ); + int FileInit (); + void ScaleOutput ( double factor ); + float ProcessReplayGain ( int mode, StreamInfo *info ); + void perform_EQ ( void ); + + int DECODE ( MPC_SAMPLE_FORMAT *buffer ); + + void UpdateBuffer ( unsigned int RING ); + int perform_jump ( int seek_needed ); + + void RESET_Synthesis ( void ); + void RESET_Globals ( void ); + + unsigned int BitsRead ( void ); + +private: + void RESET_Y ( void ); + void Lese_Bitstrom_SV6 ( void ); + void Lese_Bitstrom_SV7 ( void ); + + void Requantisierung ( const int Last_Band ); + +public: + typedef struct { + int L [36]; + int R [36]; + } QuantTyp; + + typedef struct { + unsigned int Code; + unsigned int Length; + int Value; + } HuffmanTyp; + +public: + unsigned int Speicher [MEMSIZE]; // read-buffer + unsigned int dword; // actually decoded 32bit-word + unsigned int pos; // bit-position within dword + unsigned int Zaehler; // actual index within read-buffer + + unsigned int FwdJumpInfo; + unsigned int ActDecodePos; + unsigned int FrameWasValid; + + unsigned int DecodedFrames; + unsigned int LastFrame; + unsigned int LastBitsRead; + unsigned int OverallFrames; + int SectionBitrate; // average bitrate for short section + int SampleRate; // Sample frequency + int NumberOfConsecutiveBrokenFrames; // counter for consecutive broken frames + +private: + unsigned int StreamVersion; // version of bitstream + unsigned int MS_used; // MS-coding used ? + int Max_Band; + unsigned int MPCHeaderPos; // AB: needed to support ID3v2 + //unsigned int OverallFrames; + //unsigned int DecodedFrames; + unsigned int LastValidSamples; + unsigned int TrueGaplessPresent; + + unsigned int EQ_activated; + + unsigned int WordsRead; // counts amount of decoded dwords + unsigned short* SeekTable; + + /*static*/ unsigned int __r1; + /*static*/ unsigned int __r2; + + unsigned long clips; + +private: + float EQ_gain [ 32 - FIR_BANDS ]; + float EQ_Filter [ FIR_BANDS ][ EQ_TAP ]; + + int SCF_Index_L [32] [3]; + int SCF_Index_R [32] [3]; // holds scalefactor-indices + QuantTyp Q [32]; // holds quantized samples + int Res_L [32]; + int Res_R [32]; // holds the chosen quantizer for each subband + int DSCF_Flag_L [32]; + int DSCF_Flag_R [32]; // differential SCF used? + int SCFI_L [32]; + int SCFI_R [32]; // describes order of transmitted SCF + int DSCF_Reference_L [32]; + int DSCF_Reference_R [32]; // holds last frames SCF + int MS_Flag[32]; // MS used? + + float SAVE_L [DELAY] [32]; // buffer for ... + float SAVE_R [DELAY] [32]; // ... upper subbands + float FirSave_L [FIR_BANDS] [EQ_TAP];// buffer for ... + float FirSave_R [FIR_BANDS] [EQ_TAP];// ... lowest subbands + + HuffmanTyp HuffHdr [10]; + HuffmanTyp HuffSCFI [ 4]; + HuffmanTyp HuffDSCF [16]; + HuffmanTyp* HuffQ [2] [8]; + + HuffmanTyp HuffQ1 [2] [3*3*3]; + HuffmanTyp HuffQ2 [2] [5*5]; + HuffmanTyp HuffQ3 [2] [ 7]; + HuffmanTyp HuffQ4 [2] [ 9]; + HuffmanTyp HuffQ5 [2] [15]; + HuffmanTyp HuffQ6 [2] [31]; + HuffmanTyp HuffQ7 [2] [63]; + + const HuffmanTyp* SampleHuff [18]; + HuffmanTyp SCFI_Bundle [ 8]; + HuffmanTyp DSCF_Entropie [13]; + HuffmanTyp Region_A [16]; + HuffmanTyp Region_B [ 8]; + HuffmanTyp Region_C [ 4]; + + HuffmanTyp Entropie_1 [ 3]; + HuffmanTyp Entropie_2 [ 5]; + HuffmanTyp Entropie_3 [ 7]; + HuffmanTyp Entropie_4 [ 9]; + HuffmanTyp Entropie_5 [15]; + HuffmanTyp Entropie_6 [31]; + HuffmanTyp Entropie_7 [63]; + + float V_L [V_MEM + 960]; + float V_R [V_MEM + 960]; + float Y_L [36] [32]; + float Y_R [36] [32]; + + float SCF [256]; // holds adapted scalefactors (for clipping prevention) + unsigned int Q_bit [32]; // holds amount of bits to save chosen quantizer (SV6) + unsigned int Q_res [32] [16]; // holds conversion: index -> quantizer (SV6) + +private: // functions + void Reset_BitstreamDecode ( void ); + unsigned int Bitstream_read ( const unsigned int ); + int Huffman_Decode ( const HuffmanTyp* ); // works with maximum lengths up to 14 + int Huffman_Decode_fast ( const HuffmanTyp* ); // works with maximum lengths up to 10 + int Huffman_Decode_faster ( const HuffmanTyp* ); // works with maximum lengths up to 5 + void SCFI_Bundle_read ( const HuffmanTyp*, int*, int* ); + + void Calculate_New_V ( const float* Sample, float* V ); + void Vectoring_float ( float* Data, const float* V ); + void Vectoring ( short* Data, const float* V ); + void Vectoring_dithered ( short* Data, const float* V, const float* dither ); + void GenerateDither_old ( float* p, size_t len ); + void GenerateDither ( float* p, size_t len ); + + void Reset_V ( void ); + void Synthese_Filter_float ( float* dst ); + void Synthese_Filter_opt ( short* dst ); + void Synthese_Filter_dithered ( short* dst ); + unsigned int random_int ( void ); + + void EQSet ( int on, char data[10], int preamp ); + + void Helper1 ( unsigned long bitpos ); + void Helper2 ( unsigned long bitpos ); + void Helper3 ( unsigned long bitpos, long* buffoffs ); + + void Huffman_SV6_Encoder ( void ); + void Huffman_SV6_Decoder ( void ); + void Huffman_SV7_Encoder ( void ); + void Huffman_SV7_Decoder ( void ); + + void initialisiere_Quantisierungstabellen ( void ); + void Quantisierungsmodes ( void ); // conversion: index -> quantizer (bitstream reading) + void Resort_HuffTables ( const unsigned int elements, HuffmanTyp* Table, const int offset ); + +private: + _inline int f_read ( void *ptr, size_t size) { return m_reader->read (ptr, size); }; + _inline int f_seek ( int offset, int origin) { return m_reader->seek (offset, origin); }; +}; + +#endif diff --git a/src/add-ons/media/plugins/musepack/mpc/requant.cpp b/src/add-ons/media/plugins/musepack/mpc/requant.cpp new file mode 100644 index 0000000000..77bf358d19 --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/requant.cpp @@ -0,0 +1,82 @@ +#include +#include "requant.h" + +/* C O N S T A N T S */ +// bits per sample for chosen quantizer +const unsigned int Res_bit [18] = { + 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +}; + +// coefficients for requantization +// 65536/step bzw. 65536/(2*D+1) +const float __Cc [1 + 18] = { + 111.285962475327f, // 32768/2/255*sqrt(3) + 65536.000000000000f, 21845.333333333332f, 13107.200000000001f, 9362.285714285713f, + 7281.777777777777f, 4369.066666666666f, 2114.064516129032f, 1040.253968253968f, + 516.031496062992f, 257.003921568627f, 128.250489236790f, 64.062561094819f, + 32.015632633121f, 16.003907203907f, 8.000976681723f, 4.000244155527f, + 2.000061037018f, 1.000015259021f +}; + +// offset for requantization +// 2*D+1 = steps of quantizer +const int __Dc [1 + 18] = { + 2, + 0, 1, 2, 3, 4, 7, 15, 31, 63, + 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767 +}; + +/* F U N C T I O N S */ +void +MPC_decoder::ScaleOutput ( double factor ) +{ + int n; + double f1 = factor; + double f2 = factor; + + // handles +1.58...-98.41 dB, where's scf[n] / scf[n-1] = 1.20050805774840750476 + for ( n = 0; n <= 128; n++ ) { + SCF [(unsigned char)(1+n)] = (float) f1; + SCF [(unsigned char)(1-n)] = (float) f2; + f1 *= 0.83298066476582673961; + f2 *= 1/0.83298066476582673961; + } +} + +void +MPC_decoder::Quantisierungsmodes ( void ) // conversion: index -> quantizer (bitstream reading) +{ // conversion: quantizer -> index (bitstream writing) + int Band = 0; + int i; + + do { + Q_bit [Band] = 4; + for ( i = 0; i < 16-1; i++ ) + Q_res [Band] [i] = i; + Q_res [Band][i] = 17; + Band++; + } while ( Band < 11 ); + + do { + Q_bit [Band] = 3; + for ( i = 0; i < 8-1; i++ ) + Q_res [Band] [i] = i; + Q_res [Band] [i] = 17; + Band++; + } while ( Band < 23 ); + + do { + Q_bit [Band] = 2; + for ( i = 0; i < 4-1; i++ ) + Q_res [Band] [i] = i; + Q_res [Band] [i] = 17; + Band++; + } while ( Band < 32 ); +} + +void +MPC_decoder::initialisiere_Quantisierungstabellen ( void ) +{ + Quantisierungsmodes (); + ScaleOutput ( 1.0 ); +} diff --git a/src/add-ons/media/plugins/musepack/mpc/requant.h b/src/add-ons/media/plugins/musepack/mpc/requant.h new file mode 100644 index 0000000000..67b7deb670 --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/requant.h @@ -0,0 +1,14 @@ +#ifndef _requant_h +#define _requant_h_ + +#include "mpc_dec.h" + +/* C O N S T A N T S */ +extern const unsigned int Res_bit [18]; // bits per sample for chosen quantizer +extern const float __Cc [1 + 18]; // coefficients for requantization +extern const int __Dc [1 + 18]; // offset for requantization + +#define Cc (__Cc + 1) +#define Dc (__Dc + 1) + +#endif diff --git a/src/add-ons/media/plugins/musepack/mpc/synth_filter.cpp b/src/add-ons/media/plugins/musepack/mpc/synth_filter.cpp new file mode 100644 index 0000000000..574231e3dc --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/synth_filter.cpp @@ -0,0 +1,531 @@ +#include +#include +#include "synth_filter.h" +#include "mpc_dec.h" + +// unsigned long clips = 0; + +/* C O N S T A N T S */ +#undef _ +#define _(value) (float)(value##.##L / 0x10000) + +const float Di_opt [32] [16] = { + { _( 0), _( -29), _( 213), _( -459), _( 2037), _(-5153), _( 6574), _(-37489), _(75038), _(37489), _(6574), _( 5153), _(2037), _( 459), _(213), _(29) }, + { _( -1), _( -31), _( 218), _( -519), _( 2000), _(-5517), _( 5959), _(-39336), _(74992), _(35640), _(7134), _( 4788), _(2063), _( 401), _(208), _(26) }, + { _( -1), _( -35), _( 222), _( -581), _( 1952), _(-5879), _( 5288), _(-41176), _(74856), _(33791), _(7640), _( 4425), _(2080), _( 347), _(202), _(24) }, + { _( -1), _( -38), _( 225), _( -645), _( 1893), _(-6237), _( 4561), _(-43006), _(74630), _(31947), _(8092), _( 4063), _(2087), _( 294), _(196), _(21) }, + { _( -1), _( -41), _( 227), _( -711), _( 1822), _(-6589), _( 3776), _(-44821), _(74313), _(30112), _(8492), _( 3705), _(2085), _( 244), _(190), _(19) }, + { _( -1), _( -45), _( 228), _( -779), _( 1739), _(-6935), _( 2935), _(-46617), _(73908), _(28289), _(8840), _( 3351), _(2075), _( 197), _(183), _(17) }, + { _( -1), _( -49), _( 228), _( -848), _( 1644), _(-7271), _( 2037), _(-48390), _(73415), _(26482), _(9139), _( 3004), _(2057), _( 153), _(176), _(16) }, + { _( -2), _( -53), _( 227), _( -919), _( 1535), _(-7597), _( 1082), _(-50137), _(72835), _(24694), _(9389), _( 2663), _(2032), _( 111), _(169), _(14) }, + { _( -2), _( -58), _( 224), _( -991), _( 1414), _(-7910), _( 70), _(-51853), _(72169), _(22929), _(9592), _( 2330), _(2001), _( 72), _(161), _(13) }, + { _( -2), _( -63), _( 221), _(-1064), _( 1280), _(-8209), _( -998), _(-53534), _(71420), _(21189), _(9750), _( 2006), _(1962), _( 36), _(154), _(11) }, + { _( -2), _( -68), _( 215), _(-1137), _( 1131), _(-8491), _( -2122), _(-55178), _(70590), _(19478), _(9863), _( 1692), _(1919), _( 2), _(147), _(10) }, + { _( -3), _( -73), _( 208), _(-1210), _( 970), _(-8755), _( -3300), _(-56778), _(69679), _(17799), _(9935), _( 1388), _(1870), _( -29), _(139), _( 9) }, + { _( -3), _( -79), _( 200), _(-1283), _( 794), _(-8998), _( -4533), _(-58333), _(68692), _(16155), _(9966), _( 1095), _(1817), _( -57), _(132), _( 8) }, + { _( -4), _( -85), _( 189), _(-1356), _( 605), _(-9219), _( -5818), _(-59838), _(67629), _(14548), _(9959), _( 814), _(1759), _( -83), _(125), _( 7) }, + { _( -4), _( -91), _( 177), _(-1428), _( 402), _(-9416), _( -7154), _(-61289), _(66494), _(12980), _(9916), _( 545), _(1698), _(-106), _(117), _( 7) }, + { _( -5), _( -97), _( 163), _(-1498), _( 185), _(-9585), _( -8540), _(-62684), _(65290), _(11455), _(9838), _( 288), _(1634), _(-127), _(111), _( 6) }, + { _( -5), _(-104), _( 146), _(-1567), _( -45), _(-9727), _( -9975), _(-64019), _(64019), _( 9975), _(9727), _( 45), _(1567), _(-146), _(104), _( 5) }, + { _( -6), _(-111), _( 127), _(-1634), _( -288), _(-9838), _(-11455), _(-65290), _(62684), _( 8540), _(9585), _( -185), _(1498), _(-163), _( 97), _( 5) }, + { _( -7), _(-117), _( 106), _(-1698), _( -545), _(-9916), _(-12980), _(-66494), _(61289), _( 7154), _(9416), _( -402), _(1428), _(-177), _( 91), _( 4) }, + { _( -7), _(-125), _( 83), _(-1759), _( -814), _(-9959), _(-14548), _(-67629), _(59838), _( 5818), _(9219), _( -605), _(1356), _(-189), _( 85), _( 4) }, + { _( -8), _(-132), _( 57), _(-1817), _(-1095), _(-9966), _(-16155), _(-68692), _(58333), _( 4533), _(8998), _( -794), _(1283), _(-200), _( 79), _( 3) }, + { _( -9), _(-139), _( 29), _(-1870), _(-1388), _(-9935), _(-17799), _(-69679), _(56778), _( 3300), _(8755), _( -970), _(1210), _(-208), _( 73), _( 3) }, + { _(-10), _(-147), _( -2), _(-1919), _(-1692), _(-9863), _(-19478), _(-70590), _(55178), _( 2122), _(8491), _(-1131), _(1137), _(-215), _( 68), _( 2) }, + { _(-11), _(-154), _( -36), _(-1962), _(-2006), _(-9750), _(-21189), _(-71420), _(53534), _( 998), _(8209), _(-1280), _(1064), _(-221), _( 63), _( 2) }, + { _(-13), _(-161), _( -72), _(-2001), _(-2330), _(-9592), _(-22929), _(-72169), _(51853), _( -70), _(7910), _(-1414), _( 991), _(-224), _( 58), _( 2) }, + { _(-14), _(-169), _(-111), _(-2032), _(-2663), _(-9389), _(-24694), _(-72835), _(50137), _(-1082), _(7597), _(-1535), _( 919), _(-227), _( 53), _( 2) }, + { _(-16), _(-176), _(-153), _(-2057), _(-3004), _(-9139), _(-26482), _(-73415), _(48390), _(-2037), _(7271), _(-1644), _( 848), _(-228), _( 49), _( 1) }, + { _(-17), _(-183), _(-197), _(-2075), _(-3351), _(-8840), _(-28289), _(-73908), _(46617), _(-2935), _(6935), _(-1739), _( 779), _(-228), _( 45), _( 1) }, + { _(-19), _(-190), _(-244), _(-2085), _(-3705), _(-8492), _(-30112), _(-74313), _(44821), _(-3776), _(6589), _(-1822), _( 711), _(-227), _( 41), _( 1) }, + { _(-21), _(-196), _(-294), _(-2087), _(-4063), _(-8092), _(-31947), _(-74630), _(43006), _(-4561), _(6237), _(-1893), _( 645), _(-225), _( 38), _( 1) }, + { _(-24), _(-202), _(-347), _(-2080), _(-4425), _(-7640), _(-33791), _(-74856), _(41176), _(-5288), _(5879), _(-1952), _( 581), _(-222), _( 35), _( 1) }, + { _(-26), _(-208), _(-401), _(-2063), _(-4788), _(-7134), _(-35640), _(-74992), _(39336), _(-5959), _(5517), _(-2000), _( 519), _(-218), _( 31), _( 1) } +}; + +#undef _ + +/* F U N K T I O N E N */ +void +MPC_decoder::Reset_V ( void ) +{ + memset ( V_L, 0, sizeof V_L ); + memset ( V_R, 0, sizeof V_R ); +} + +void +MPC_decoder::Calculate_New_V ( const float* Sample, float* V ) +{ + // Calculating new V-buffer values for left channel + // calculate new V-values (ISO-11172-3, p. 39) + // based upon fast-MDCT algorithm by Byeong Gi Lee + /*static*/ float A00, A01, A02, A03, A04, A05, A06, A07, A08, A09, A10, A11, A12, A13, A14, A15; + /*static*/ float B00, B01, B02, B03, B04, B05, B06, B07, B08, B09, B10, B11, B12, B13, B14, B15; + float tmp; + + A00 = Sample[ 0] + Sample[31]; + A01 = Sample[ 1] + Sample[30]; + A02 = Sample[ 2] + Sample[29]; + A03 = Sample[ 3] + Sample[28]; + A04 = Sample[ 4] + Sample[27]; + A05 = Sample[ 5] + Sample[26]; + A06 = Sample[ 6] + Sample[25]; + A07 = Sample[ 7] + Sample[24]; + A08 = Sample[ 8] + Sample[23]; + A09 = Sample[ 9] + Sample[22]; + A10 = Sample[10] + Sample[21]; + A11 = Sample[11] + Sample[20]; + A12 = Sample[12] + Sample[19]; + A13 = Sample[13] + Sample[18]; + A14 = Sample[14] + Sample[17]; + A15 = Sample[15] + Sample[16]; + + B00 = A00 + A15; + B01 = A01 + A14; + B02 = A02 + A13; + B03 = A03 + A12; + B04 = A04 + A11; + B05 = A05 + A10; + B06 = A06 + A09; + B07 = A07 + A08; + B08 = (A00 - A15) * 0.5024192929f; + B09 = (A01 - A14) * 0.5224986076f; + B10 = (A02 - A13) * 0.5669440627f; + B11 = (A03 - A12) * 0.6468217969f; + B12 = (A04 - A11) * 0.7881546021f; + B13 = (A05 - A10) * 1.0606776476f; + B14 = (A06 - A09) * 1.7224471569f; + B15 = (A07 - A08) * 5.1011486053f; + + A00 = B00 + B07; + A01 = B01 + B06; + A02 = B02 + B05; + A03 = B03 + B04; + A04 = (B00 - B07) * 0.5097956061f; + A05 = (B01 - B06) * 0.6013448834f; + A06 = (B02 - B05) * 0.8999761939f; + A07 = (B03 - B04) * 2.5629155636f; + A08 = B08 + B15; + A09 = B09 + B14; + A10 = B10 + B13; + A11 = B11 + B12; + A12 = (B08 - B15) * 0.5097956061f; + A13 = (B09 - B14) * 0.6013448834f; + A14 = (B10 - B13) * 0.8999761939f; + A15 = (B11 - B12) * 2.5629155636f; + + B00 = A00 + A03; + B01 = A01 + A02; + B02 = (A00 - A03) * 0.5411961079f; + B03 = (A01 - A02) * 1.3065630198f; + B04 = A04 + A07; + B05 = A05 + A06; + B06 = (A04 - A07) * 0.5411961079f; + B07 = (A05 - A06) * 1.3065630198f; + B08 = A08 + A11; + B09 = A09 + A10; + B10 = (A08 - A11) * 0.5411961079f; + B11 = (A09 - A10) * 1.3065630198f; + B12 = A12 + A15; + B13 = A13 + A14; + B14 = (A12 - A15) * 0.5411961079f; + B15 = (A13 - A14) * 1.3065630198f; + + A00 = B00 + B01; + A01 = (B00 - B01) * 0.7071067691f; + A02 = B02 + B03; + A03 = (B02 - B03) * 0.7071067691f; + A04 = B04 + B05; + A05 = (B04 - B05) * 0.7071067691f; + A06 = B06 + B07; + A07 = (B06 - B07) * 0.7071067691f; + A08 = B08 + B09; + A09 = (B08 - B09) * 0.7071067691f; + A10 = B10 + B11; + A11 = (B10 - B11) * 0.7071067691f; + A12 = B12 + B13; + A13 = (B12 - B13) * 0.7071067691f; + A14 = B14 + B15; + A15 = (B14 - B15) * 0.7071067691f; + + V[48] = -A00; + V[ 0] = A01; + V[40] = -A02 - (V[ 8] = A03); + V[36] = -((V[ 4] = A05 + (V[12] = A07)) + A06); + V[44] = - A04 - A06 - A07; + V[ 6] = (V[10] = A11 + (V[14] = A15)) + A13; + V[38] = (V[34] = -(V[ 2] = A09 + A13 + A15) - A14) + A09 - A10 - A11; + V[46] = (tmp = -(A12 + A14 + A15)) - A08; + V[42] = tmp - A10 - A11; + + A00 = (Sample[ 0] - Sample[31]) * 0.5006030202f; + A01 = (Sample[ 1] - Sample[30]) * 0.5054709315f; + A02 = (Sample[ 2] - Sample[29]) * 0.5154473186f; + A03 = (Sample[ 3] - Sample[28]) * 0.5310425758f; + A04 = (Sample[ 4] - Sample[27]) * 0.5531039238f; + A05 = (Sample[ 5] - Sample[26]) * 0.5829349756f; + A06 = (Sample[ 6] - Sample[25]) * 0.6225041151f; + A07 = (Sample[ 7] - Sample[24]) * 0.6748083234f; + A08 = (Sample[ 8] - Sample[23]) * 0.7445362806f; + A09 = (Sample[ 9] - Sample[22]) * 0.8393496275f; + A10 = (Sample[10] - Sample[21]) * 0.9725682139f; + A11 = (Sample[11] - Sample[20]) * 1.1694399118f; + A12 = (Sample[12] - Sample[19]) * 1.4841645956f; + A13 = (Sample[13] - Sample[18]) * 2.0577809811f; + A14 = (Sample[14] - Sample[17]) * 3.4076085091f; + A15 = (Sample[15] - Sample[16]) *10.1900081635f; + + B00 = A00 + A15; + B01 = A01 + A14; + B02 = A02 + A13; + B03 = A03 + A12; + B04 = A04 + A11; + B05 = A05 + A10; + B06 = A06 + A09; + B07 = A07 + A08; + B08 = (A00 - A15) * 0.5024192929f; + B09 = (A01 - A14) * 0.5224986076f; + B10 = (A02 - A13) * 0.5669440627f; + B11 = (A03 - A12) * 0.6468217969f; + B12 = (A04 - A11) * 0.7881546021f; + B13 = (A05 - A10) * 1.0606776476f; + B14 = (A06 - A09) * 1.7224471569f; + B15 = (A07 - A08) * 5.1011486053f; + + A00 = B00 + B07; + A01 = B01 + B06; + A02 = B02 + B05; + A03 = B03 + B04; + A04 = (B00 - B07) * 0.5097956061f; + A05 = (B01 - B06) * 0.6013448834f; + A06 = (B02 - B05) * 0.8999761939f; + A07 = (B03 - B04) * 2.5629155636f; + A08 = B08 + B15; + A09 = B09 + B14; + A10 = B10 + B13; + A11 = B11 + B12; + A12 = (B08 - B15) * 0.5097956061f; + A13 = (B09 - B14) * 0.6013448834f; + A14 = (B10 - B13) * 0.8999761939f; + A15 = (B11 - B12) * 2.5629155636f; + + B00 = A00 + A03; + B01 = A01 + A02; + B02 = (A00 - A03) * 0.5411961079f; + B03 = (A01 - A02) * 1.3065630198f; + B04 = A04 + A07; + B05 = A05 + A06; + B06 = (A04 - A07) * 0.5411961079f; + B07 = (A05 - A06) * 1.3065630198f; + B08 = A08 + A11; + B09 = A09 + A10; + B10 = (A08 - A11) * 0.5411961079f; + B11 = (A09 - A10) * 1.3065630198f; + B12 = A12 + A15; + B13 = A13 + A14; + B14 = (A12 - A15) * 0.5411961079f; + B15 = (A13 - A14) * 1.3065630198f; + + A00 = B00 + B01; + A01 = (B00 - B01) * 0.7071067691f; + A02 = B02 + B03; + A03 = (B02 - B03) * 0.7071067691f; + A04 = B04 + B05; + A05 = (B04 - B05) * 0.7071067691f; + A06 = B06 + B07; + A07 = (B06 - B07) * 0.7071067691f; + A08 = B08 + B09; + A09 = (B08 - B09) * 0.7071067691f; + A10 = B10 + B11; + A11 = (B10 - B11) * 0.7071067691f; + A12 = B12 + B13; + A13 = (B12 - B13) * 0.7071067691f; + A14 = B14 + B15; + A15 = (B14 - B15) * 0.7071067691f; + + // mehrfach verwendete Ausdrücke: A04+A06+A07, A09+A13+A15 + V[ 5] = (V[11] = (V[13] = A07 + (V[15] = A15)) + A11) + A05 + A13; + V[ 7] = (V[ 9] = A03 + A11 + A15) + A13; + V[33] = -(V[ 1] = A01 + A09 + A13 + A15) - A14; + V[35] = -(V[ 3] = A05 + A07 + A09 + A13 + A15) - A06 - A14; + V[37] = (tmp = -(A10 + A11 + A13 + A14 + A15)) - A05 - A06 - A07; + V[39] = tmp - A02 - A03; // abhängig vom Befehl drüber + V[41] = (tmp += A13 - A12) - A02 - A03; // abhängig vom Befehl 2 drüber + V[43] = tmp - A04 - A06 - A07; // abhängig von Befehlen 1 und 3 drüber + V[47] = (tmp = -(A08 + A12 + A14 + A15)) - A00; + V[45] = tmp - A04 - A06 - A07; // abhängig vom Befehl drüber + + V[32] = -V[ 0]; + V[31] = -V[ 1]; + V[30] = -V[ 2]; + V[29] = -V[ 3]; + V[28] = -V[ 4]; + V[27] = -V[ 5]; + V[26] = -V[ 6]; + V[25] = -V[ 7]; + V[24] = -V[ 8]; + V[23] = -V[ 9]; + V[22] = -V[10]; + V[21] = -V[11]; + V[20] = -V[12]; + V[19] = -V[13]; + V[18] = -V[14]; + V[17] = -V[15]; + + V[63] = V[33]; + V[62] = V[34]; + V[61] = V[35]; + V[60] = V[36]; + V[59] = V[37]; + V[58] = V[38]; + V[57] = V[39]; + V[56] = V[40]; + V[55] = V[41]; + V[54] = V[42]; + V[53] = V[43]; + V[52] = V[44]; + V[51] = V[45]; + V[50] = V[46]; + V[49] = V[47]; +} + +void +MPC_decoder::Vectoring_float ( float* Data, const float* V ) +{ + const float* D = (float*) Di_opt; + double Sum; + int k; + //int tmp; + + for ( k = 0; k < 32; k++, D += 16, V++ ) { + Sum = ( V[ 0]*D[ 0] + V[ 96]*D[ 1] + V[128]*D[ 2] + V[224]*D[ 3] + + V[256]*D[ 4] + V[352]*D[ 5] + V[384]*D[ 6] + V[480]*D[ 7] + + V[512]*D[ 8] + V[608]*D[ 9] + V[640]*D[10] + V[736]*D[11] + + V[768]*D[12] + V[864]*D[13] + V[896]*D[14] + V[992]*D[15] ); // + 0xFF8000; + //ftol ( Sum, *Data ); // copy to PCM (ftol mit Sättigung, +0xFF8000 gehört bereits dazu) + *Data = (float)(Sum * (1.0/32768.0)); + Data += 2; + } +} + +void +MPC_decoder::Synthese_Filter_float ( float* OutData ) +{ + int n; + float* V; + const float* Y; + + /********* left channel ********/ + memmove ( V_L + V_MEM, V_L, 960 * sizeof(float) ); + V = V_L + V_MEM; + Y = Y_L [0]; + + for ( n = 0; n < 36; n++, OutData += 64, Y += 32 ) { + V -= 64; + Calculate_New_V ( Y, V ); + Vectoring_float ( OutData, V ); + } + // set pointer to OutData[1] for filling right channel + OutData -= 2*1152 - 1; + + /******** right channel ********/ + memmove ( V_R + V_MEM, V_R, 960 * sizeof(float) ); + V = V_R + V_MEM; + Y = Y_R [0]; + + for ( n = 0; n < 36; n++, OutData += 64, Y += 32 ) { + V -= 64; + Calculate_New_V ( Y, V ); + Vectoring_float ( OutData, V ); + } +} + +void +MPC_decoder::Vectoring ( short* Data, const float* V ) +{ + const float* D = (float*) Di_opt; + float Sum; + int k; + int tmp; + + for ( k = 0; k < 32; k++, D += 16, V++ ) { + Sum = V[ 0]*D[ 0] + V[ 96]*D[ 1] + V[128]*D[ 2] + V[224]*D[ 3] + + V[256]*D[ 4] + V[352]*D[ 5] + V[384]*D[ 6] + V[480]*D[ 7] + + V[512]*D[ 8] + V[608]*D[ 9] + V[640]*D[10] + V[736]*D[11] + + V[768]*D[12] + V[864]*D[13] + V[896]*D[14] + V[992]*D[15] + 0xFF8000; + ftol ( Sum, *Data ); // copy to PCM (ftol mit Sättigung, +0xFF8000 gehört bereits dazu) + Data += 2; + } +} + +void +MPC_decoder::Synthese_Filter_opt ( short* OutData ) +{ + int n; + float* V; + const float* Y; + + /********* left channel ********/ + memmove ( V_L + V_MEM, V_L, 960 * sizeof(float) ); + V = V_L + V_MEM; + Y = Y_L [0]; + + for ( n = 0; n < 36; n++, OutData += 64, Y += 32 ) { + V -= 64; + Calculate_New_V ( Y, V ); + Vectoring ( OutData, V ); + } + // set pointer to OutData[1] for filling right channel + OutData -= 2*1152 - 1; + + /******** right channel ********/ + memmove ( V_R + V_MEM, V_R, 960 * sizeof(float) ); + V = V_R + V_MEM; + Y = Y_R [0]; + + for ( n = 0; n < 36; n++, OutData += 64, Y += 32 ) { + V -= 64; + Calculate_New_V ( Y, V ); + Vectoring ( OutData, V ); + } +} + +/*******************************************/ +/* */ +/* dithered synthesis */ +/* */ +/*******************************************/ + +static const unsigned char Parity [256] = { // parity + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0 +}; + +/* + * This is a simple random number generator with good quality for audio purposes. + * It consists of two polycounters with opposite rotation direction and different + * periods. The periods are coprime, so the total period is the product of both. + * + * ------------------------------------------------------------------------------------------------- + * +-> |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0| + * | ------------------------------------------------------------------------------------------------- + * | | | | | | | + * | +--+--+--+-XOR-+--------+ + * | | + * +--------------------------------------------------------------------------------------+ + * + * ------------------------------------------------------------------------------------------------- + * |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0| <-+ + * ------------------------------------------------------------------------------------------------- | + * | | | | | + * +--+----XOR----+--+ | + * | | + * +----------------------------------------------------------------------------------------+ + * + * + * The first has an period of 3*5*17*257*65537, the second of 7*47*73*178481, + * which gives a period of 18.410.713.077.675.721.215. The result is the + * XORed values of both generators. + */ + +unsigned int +MPC_decoder::random_int ( void ) +{ +#if 1 + unsigned int t1, t2, t3, t4; + + t3 = t1 = __r1; t4 = t2 = __r2; // Parity calculation is done via table lookup, this is also available + t1 &= 0xF5; t2 >>= 25; // on CPUs without parity, can be implemented in C and avoid unpredictable + t1 = Parity [t1]; t2 &= 0x63; // jumps and slow rotate through the carry flag operations. + t1 <<= 31; t2 = Parity [t2]; + + return (__r1 = (t3 >> 1) | t1 ) ^ (__r2 = (t4 + t4) | t2 ); +#else + return (__r1 = (__r1 >> 1) | ((unsigned int)Parity [__r1 & 0xF5] << 31) ) ^ + (__r2 = (__r2 << 1) | (unsigned int)Parity [(__r2 >> 25) & 0x63] ); +#endif +} + +// generates triangular dither +void +MPC_decoder::GenerateDither_old ( float* p, size_t len ) +{ + while (len--) + *p++ = ( (float)(int)random_int() + (float)(int)random_int() ) * (1.f/65536.f/65536.f); +} + +void +MPC_decoder::GenerateDither ( float* p, size_t len ) +{ + /*static*/ int last = 0; + int tmp; + + while (len--) { + tmp = (int) random_int(); + *p++ = ((float)tmp - last) * (1.f/65536.f/65536.f); + last = tmp; + } +} + +// dithered vectoring +void +MPC_decoder::Vectoring_dithered ( short* Data, const float* V, const float* dither ) +{ + const float* D = (float*) Di_opt; + float Sum; + int k; + int tmp; + + for ( k = 0; k < 32; k++, D += 16, V++ ) { + Sum = V[ 0]*D[ 0] + V[ 96]*D[ 1] + V[128]*D[ 2] + V[224]*D[ 3] + + V[256]*D[ 4] + V[352]*D[ 5] + V[384]*D[ 6] + V[480]*D[ 7] + + V[512]*D[ 8] + V[608]*D[ 9] + V[640]*D[10] + V[736]*D[11] + + V[768]*D[12] + V[864]*D[13] + V[896]*D[14] + V[992]*D[15] + *dither++ + 0xFF8000 ; + ftol ( Sum, *Data ); // copy to PCM (ftol mit Sättigung, +0xFF8000 gehört bereits dazu) + Data += 2; + } +} + +// dithered synthesis +void +MPC_decoder::Synthese_Filter_dithered ( short* OutData ) +{ + int n; + float* V; + float DitherData [36 * 32]; + const float* Y; + + GenerateDither ( DitherData, 32*36 ); + /********* left channel ********/ + memmove ( V_L + V_MEM, V_L, 960 * sizeof(float) ); + V = V_L + V_MEM; + Y = Y_L [0]; + + for ( n = 0; n < 36; n++, OutData += 64, Y += 32 ) { + V -= 64; + Calculate_New_V ( Y, V ); + Vectoring_dithered ( OutData, V, DitherData + 32*n ); + } + // set pointer to OutData[1] for filling right channel + OutData -= 2*1152 - 1; + + /******** right channel ********/ + memmove ( V_R + V_MEM, V_R, 960 * sizeof(float) ); + V = V_R + V_MEM; + Y = Y_R [0]; + + for ( n = 0; n < 36; n++, OutData += 64, Y += 32 ) { + V -= 64; + Calculate_New_V ( Y, V ); + Vectoring_dithered ( OutData, V, DitherData + 32*n ); + } +} + +/* end of synth_filter.c */ diff --git a/src/add-ons/media/plugins/musepack/mpc/synth_filter.h b/src/add-ons/media/plugins/musepack/mpc/synth_filter.h new file mode 100644 index 0000000000..d9a7f64a45 --- /dev/null +++ b/src/add-ons/media/plugins/musepack/mpc/synth_filter.h @@ -0,0 +1,14 @@ +#ifndef _synth_filter_h_ +#define _synth_filter_h_ + +#include "mpc_dec.h" + +/* D E F I N E S */ +#define ftol(A,B) \ + { tmp = *(int*) & A - 0x4B7F8000; \ + if ( tmp != (short)tmp ) \ + tmp = (tmp>>31) ^ 0x7FFF, clips++; \ + B = (short) tmp; \ + } + +#endif