1 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
2  *
3  *  Use of this source code is governed by a BSD-style license that can
4  *  be found in the License.html file in the root of the source tree.
5  */
6 
7 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 //
9 // Source : http://www.wavpack.com/file_format.txt
10 //
11 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 
13 //---------------------------------------------------------------------------
14 // Pre-compilation
15 #include "MediaInfo/PreComp.h"
16 #ifdef __BORLANDC__
17     #pragma hdrstop
18 #endif
19 //---------------------------------------------------------------------------
20 
21 //---------------------------------------------------------------------------
22 #include "MediaInfo/Setup.h"
23 //---------------------------------------------------------------------------
24 
25 //---------------------------------------------------------------------------
26 #if defined(MEDIAINFO_WVPK_YES)
27 //---------------------------------------------------------------------------
28 
29 //---------------------------------------------------------------------------
30 #include "MediaInfo/Audio/File_Wvpk.h"
31 //---------------------------------------------------------------------------
32 
33 namespace MediaInfoLib
34 {
35 
36 //***************************************************************************
37 // Constants
38 //***************************************************************************
39 
40 //---------------------------------------------------------------------------
41 static const int16u Wvpk_Resolution[]=
42 {
43      8,
44     16,
45     24,
46     32,
47 };
48 
49 //---------------------------------------------------------------------------
50 static const int32u Wvpk_SamplingRate[]=
51 {
52       6000,
53       8000,
54       9600,
55      11025,
56      12000,
57      16000,
58      22050,
59      24000,
60      32000,
61      44100,
62      48000,
63      64000,
64      88200,
65      96000,
66     192000,
67          0,
68 };
69 
70 //---------------------------------------------------------------------------
Wvpk_id(int8u ID)71 static const char* Wvpk_id(int8u ID)
72 {
73     switch (ID)
74     {
75         case 0x00 : return "could be used to pad WavPack blocks";
76         case 0x02 : return "decorrelation terms & deltas";
77         case 0x03 : return "initial decorrelation weights";
78         case 0x04 : return "decorrelation sample history";
79         case 0x05 : return "initial entropy variables";
80         case 0x06 : return "entropy variables specific to hybrid mode";
81         case 0x07 : return "info needed for hybrid lossless (wvc) mode";
82         case 0x08 : return "specific info for floating point decode";
83         case 0x09 : return "specific info for decoding integers > 24 bits";
84         case 0x0A : return "normal compressed audio bitstream (wv file)";
85         case 0x0B : return "correction file bitstream (wvc file)";
86         case 0x0C : return "special extended bitstream for floating point data or integers > 24 bit";
87         case 0x0D : return "contains channel count and channel_mask";
88         case 0x21 : return "RIFF header for .wav files (before audio)";
89         case 0x22 : return "RIFF trailer for .wav files (after audio)";
90         case 0x25 : return "some encoding details for info purposes";
91         case 0x26 : return "16-byte MD5 sum of raw audio data";
92         case 0x27 : return "non-standard sampling rate info";
93         default:    return "";
94     }
95 }
96 
97 //---------------------------------------------------------------------------
98 extern std::string ExtensibleWave_ChannelMask_ChannelLayout(int32u ChannelMask); //In Multiple/File_Riff_Elements.cpp
99 
100 //***************************************************************************
101 // Constructor/Destructor
102 //***************************************************************************
103 
104 //---------------------------------------------------------------------------
File_Wvpk()105 File_Wvpk::File_Wvpk()
106 :File__Analyze(), File__Tags_Helper()
107 {
108     //File__Tags_Helper
109     Base=this;
110 
111     //Configuration
112     MustSynchronize=true;
113     Buffer_TotalBytes_FirstSynched_Max=32*1024;
114 
115     //In
116     Frame_Count_Valid=2;
117     FromMKV=false;
118     FromMKV_CodecPrivateParsed=false;
119 
120     //Temp - Technical info
121     total_samples_FirstFrame=(int32u)-1;
122     block_index_FirstFrame=0;
123     block_index_LastFrame=0;
124     SamplingRate=(int8u)-1;
125     num_channels=0;
126     channel_mask=0;
127     mono=false;
128     hybrid=false;
129     resolution0=false;
130     resolution1=false;
131 }
132 
133 //***************************************************************************
134 // Streams management
135 //***************************************************************************
136 
137 //---------------------------------------------------------------------------
Streams_Finish()138 void File_Wvpk::Streams_Finish()
139 {
140     Fill(Stream_Audio, 0, Audio_BitRate_Mode, "VBR");
141 
142     //Specific case
143     if (FromMKV)
144         return;
145 
146     //Duration
147     if (SamplingRate<15)
148     {
149         int64u Duration=(((int64u)(block_index_LastFrame+block_samples_LastFrame-block_index_FirstFrame))*1000/Wvpk_SamplingRate[SamplingRate]); //Don't forget the last frame with block_samples...
150         int64u CompressedSize=File_Size-TagsSize;
151         int64u UncompressedSize=Duration*(mono?1:2)*Wvpk_Resolution[(resolution1?1:0)*2+(resolution0?1:0)]*Wvpk_SamplingRate[SamplingRate]/8/1000;
152         float32 CompressionRatio=((float32)UncompressedSize)/CompressedSize;
153         Fill(Stream_Audio, 0, Audio_StreamSize, CompressedSize, 3, true);
154         Fill(Stream_Audio, 0, Audio_Duration, Duration, 10, true);
155         Fill(Stream_Audio, 0, Audio_Compression_Ratio, CompressionRatio, 3, true);
156     }
157 
158     File__Tags_Helper::Streams_Finish();
159 }
160 
161 //***************************************************************************
162 // Buffer - File header
163 //***************************************************************************
164 
165 //---------------------------------------------------------------------------
FileHeader_Begin()166 bool File_Wvpk::FileHeader_Begin()
167 {
168     //Element_Size
169     if (Buffer_Size<2)
170         return false; //Must wait for more data
171 
172     if (CC2(Buffer)==0x4D5A) //"MZ"
173     {
174         File__Tags_Helper::Reject("WavPack");
175         return false; //Executable with WavPack data are currently not well supported --> It is preferable to set them as executable
176     }
177 
178     //All should be OK...
179     return true;
180 }
181 
182 //***************************************************************************
183 // Buffer - Synchro
184 //***************************************************************************
185 
186 //---------------------------------------------------------------------------
Synchronize()187 bool File_Wvpk::Synchronize()
188 {
189     //Specific case
190     if (FromMKV)
191         return true;
192 
193     //Tags
194     bool Tag_Found;
195     if (!File__Tags_Helper::Synchronize(Tag_Found))
196         return false;
197     if (Tag_Found)
198         return true;
199 
200     //Synchronizing
201     while (Buffer_Offset+4<=Buffer_Size)
202     {
203         while (Buffer_Offset+4<=Buffer_Size && (Buffer[Buffer_Offset  ]!=0x77
204                                              || Buffer[Buffer_Offset+1]!=0x76
205                                              || Buffer[Buffer_Offset+2]!=0x70
206                                              || Buffer[Buffer_Offset+3]!=0x6B)) //"wvpk"
207             Buffer_Offset++;
208 
209         if (Buffer_Offset+4<=Buffer_Size)//Testing if size is coherant
210         {
211             //Testing next start, to be sure
212             size_t Size=LittleEndian2int32u(Buffer+Buffer_Offset+4)+8;
213             if (Buffer_Offset+Size+4>Buffer_Size)
214                 return false; //Need more data
215 
216             //Testing
217             if (Buffer[Buffer_Offset+Size  ]!=0x77
218              || Buffer[Buffer_Offset+Size+1]!=0x76
219              || Buffer[Buffer_Offset+Size+2]!=0x70
220              || Buffer[Buffer_Offset+Size+3]!=0x6B) //"wvpk"
221                 Buffer_Offset++;
222             else
223                 break; //while()
224         }
225     }
226 
227     //Parsing last bytes if needed
228     if (Buffer_Offset+4>Buffer_Size)
229     {
230         if (Buffer_Offset+3==Buffer_Size && CC3(Buffer+Buffer_Offset)!=0x777670)   //"wvp"
231             Buffer_Offset++;
232         if (Buffer_Offset+2==Buffer_Size && CC2(Buffer+Buffer_Offset)!=0x7776)     //"wv"
233             Buffer_Offset++;
234         if (Buffer_Offset+1==Buffer_Size && CC1(Buffer+Buffer_Offset)!=0x77)       //"w"
235             Buffer_Offset++;
236         return false;
237     }
238 
239     //Synched is OK
240     return true;
241 }
242 
243 //---------------------------------------------------------------------------
Synched_Test()244 bool File_Wvpk::Synched_Test()
245 {
246     //Specific case
247     if (FromMKV)
248         return true;
249 
250     //Tags
251     if (!File__Tags_Helper::Synched_Test())
252         return false;
253 
254     //Must have enough buffer for having header
255     if (Buffer_Offset+3>Buffer_Size)
256         return false;
257 
258     //Quick test of synchro
259     if (Buffer[Buffer_Offset  ]!=0x77
260      || Buffer[Buffer_Offset+1]!=0x76
261      || Buffer[Buffer_Offset+2]!=0x70
262      || Buffer[Buffer_Offset+3]!=0x6B) //"wvpk"
263         Synched=false;
264 
265     //We continue
266     return true;
267 }
268 
269 //***************************************************************************
270 // Format
271 //***************************************************************************
272 
273 //---------------------------------------------------------------------------
Read_Buffer_Continue()274 void File_Wvpk::Read_Buffer_Continue()
275 {
276     //Tags
277     if (!FromMKV)
278         File__Tags_Helper::Read_Buffer_Continue();
279 }
280 
281 //***************************************************************************
282 // Buffer - Per element
283 //***************************************************************************
284 
285 //---------------------------------------------------------------------------
Header_Parse()286 void File_Wvpk::Header_Parse()
287 {
288     //Specific cases
289     if (FromMKV)
290     {
291         Header_Fill_Size(Element_Size);
292         Header_Fill_Code(0, "Block");
293         return;
294     }
295 
296     //Parsing
297     int32u ckSize;
298     Skip_C4(                                                    "ckID");
299     Get_L4 (ckSize,                                             "ckSize");
300 
301     //Filling
302     Header_Fill_Size(8+ckSize);
303     Header_Fill_Code(0, "Block");
304 }
305 
306 //---------------------------------------------------------------------------
Data_Parse()307 void File_Wvpk::Data_Parse()
308 {
309     //Specific
310     if (FromMKV && !FromMKV_CodecPrivateParsed)
311     {
312         //Parsing
313         Get_L2 (version,                                        "version");
314 
315         FILLING_BEGIN();
316         FromMKV_CodecPrivateParsed=true;
317         FILLING_END();
318         return;
319     }
320 
321     //Counting
322     Frame_Count++;
323 
324     //Parsing
325     Element_Begin1("Block Header");
326     if (!FromMKV)
327         Get_L2 (version,                                        "version");
328     if (version/0x100==0x4)
329     {
330         while (Element_Offset<Element_Size)
331         {
332             int32u total_samples=(int32u)-1, block_index=(int32u)-1, block_samples=0, flags, blocksize=(int32u)-1;
333             bool initial_block=true, final_block=true;
334             if (!FromMKV)
335             {
336                 Skip_L1(                                            "track_no");
337                 Skip_L1(                                            "index_no");
338                 Get_L4 (total_samples,                              "total_samples");
339                 Get_L4 (block_index,                                "block_index");
340             }
341             if (!FromMKV || Element_Offset==0)
342                 Get_L4 (block_samples,                              "block_samples");
343             if (block_samples!=0) //empty frames have other values empty
344             {
345                 if (!FromMKV)
346                 {
347                     if (block_index==0) //Only the frame with block_index==0
348                         total_samples_FirstFrame=total_samples; //Note: total_samples is not trustable for a cutted file
349                     if (Frame_Count==1)
350                         block_index_FirstFrame=block_index; //Save the block_index of the first block
351                     block_index_LastFrame=block_index;
352                     block_samples_LastFrame=block_samples;
353                 }
354                 Get_L4 (flags,                                      "flags");
355                     Get_Flags (flags,  0, resolution0,              "resolution0");
356                     Get_Flags (flags,  1, resolution1,              "resolution1");
357                     Get_Flags (flags,  2, mono,                     "mono");
358                     Get_Flags (flags,  3, hybrid,                   "hybrid");
359                     Get_Flags (flags,  4, joint_stereo,             "joint stereo");
360                     Get_Flags (flags,  5, cross_channel_decorrelation, "cross-channel decorrelation");
361                     Skip_Flags(flags,  6,                           "hybrid noise shaping");
362                     Skip_Flags(flags,  7,                           "floating point data");
363                     Skip_Flags(flags,  8,                           "extended size integers");
364                     Skip_Flags(flags,  9,                           "hybrid mode parameters control bitrate");
365                     Skip_Flags(flags, 10,                           "hybrid noise balanced between channels");
366                     Get_Flags (flags, 11, initial_block,            "initial block in sequence");
367                     Get_Flags (flags, 12, final_block,              "final block in sequence");
368                     Skip_Flags(flags, 13,                           "amount of data left-shift after decode");
369                     Skip_Flags(flags, 14,                           "amount of data left-shift after decode");
370                     Skip_Flags(flags, 15,                           "amount of data left-shift after decode");
371                     Skip_Flags(flags, 16,                           "amount of data left-shift after decode");
372                     Skip_Flags(flags, 17,                           "amount of data left-shift after decode");
373                     Skip_Flags(flags, 18,                           "maximum magnitude of decoded data");
374                     Skip_Flags(flags, 19,                           "maximum magnitude of decoded data");
375                     Skip_Flags(flags, 20,                           "maximum magnitude of decoded data");
376                     Skip_Flags(flags, 21,                           "maximum magnitude of decoded data");
377                     Skip_Flags(flags, 22,                           "maximum magnitude of decoded data");
378                     Skip_Flags(flags, 23,                           "sampling rate");
379                     Skip_Flags(flags, 24,                           "sampling rate");
380                     Skip_Flags(flags, 25,                           "sampling rate");
381                     Skip_Flags(flags, 26,                           "sampling rate"); SamplingRate=(int8u)(((flags>>23)&0xF)); Param_Info1(Wvpk_SamplingRate[SamplingRate]);
382                     Skip_Flags(flags, 27,                           "reserved");
383                     Skip_Flags(flags, 28,                           "reserved");
384                     Skip_Flags(flags, 29,                           "use IIR for negative hybrid noise shaping");
385                     Skip_Flags(flags, 30,                           "false stereo");
386                     Skip_Flags(flags, 31,                           "reserved");
387             }
388             else
389             {
390                 Skip_L4(                                            "flags (empty)");
391 
392                 //Counting
393                 Frame_Count--; //This is not a real frame
394             }
395             Skip_L4(                                                "crc");
396             Element_End0();
397 
398             int64u End=Element_Size;
399             if (FromMKV && !(initial_block && final_block))
400             {
401                 Get_L4 (blocksize,                                  "blocksize");
402                 End=Element_Offset+blocksize;
403                 if (End>=Element_Size)
404                     End=Element_Size;
405             }
406 
407             //Sub-block
408             int8u id;
409             while (Element_Offset<End)
410             {
411                 Element_Begin0();
412                 int32u word_size;
413                 bool large, odd_size;
414                 BS_Begin();
415                 Get_SB (large,                                      "large");
416                 Get_SB (odd_size,                                   "odd_size");
417                 Get_S1 (6, id,                                      "id"); Element_Info1(Wvpk_id(id));
418                 BS_End();
419                 if (large)
420                 {
421                     Get_L3 (word_size,                              "word_size");
422                 }
423                 else
424                 {
425                     int8u word_size1;
426                     Get_L1 (word_size1,                             "word_size");
427                     word_size=word_size1;
428                 }
429                 if (word_size==0 && odd_size)
430                     Size=0; //Problem!
431                 else
432                     Size=word_size*2-(odd_size?1:0);
433                 Element_Name(Ztring().From_CC1(id));
434                 switch (id)
435                 {
436                     case 0x07 : id_07(); break;
437                     case 0x0D : id_0D(); break;
438                     case 0x25 : id_25(); break;
439                     default   : if (word_size)
440                                     Skip_XX(Size,                   "data");
441                 }
442                 if (odd_size)
443                     Skip_XX(1,                                      "padding");
444                 Element_End0();
445             }
446         }
447     }
448 
449     //Filling
450     if (!Status[IsAccepted] && Frame_Count>=Frame_Count_Valid)
451     {
452         File__Tags_Helper::Accept("WavPack");
453         Data_Parse_Fill();
454     }
455 }
456 
457 //---------------------------------------------------------------------------
Data_Parse_Fill()458 void File_Wvpk::Data_Parse_Fill()
459 {
460     //Filling
461     File__Tags_Helper::Stream_Prepare(Stream_Audio);
462     Fill(Stream_Audio, 0, Audio_Format, "WavPack");
463     Ztring Version_Minor=Ztring::ToZtring(version%0x100);
464     if (Version_Minor.size()==1)
465         Version_Minor.insert(0, 1, __T('0'));
466     Fill(Stream_Audio, 0, Audio_Format_Profile, Ztring::ToZtring(version/0x100)+__T('.')+Version_Minor);
467     Fill(Stream_Audio, 0, Audio_Codec, "Wavpack");
468     Fill(Stream_Audio, 0, Audio_BitDepth, Wvpk_Resolution[(resolution1?1:0)*2+(resolution0?1:0)]);
469     Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, num_channels?num_channels:(mono?1:2));
470     if (channel_mask)
471     {
472         Ztring Channels_Positions, Channels_Positions2;
473         if (channel_mask&0x00C7)
474         {
475             int8u Count=0;
476             Channels_Positions+=__T("Front:");
477             if (channel_mask&0x0001)
478             {
479                 Channels_Positions+=__T(" L");
480                 Count++;
481             }
482             if (channel_mask&0x0004)
483             {
484                 Channels_Positions+=__T(" C");
485                 Count++;
486             }
487             if (channel_mask&0x0040)
488             {
489                 Channels_Positions+=__T(" C");
490                 Count++;
491             }
492             if (channel_mask&0x0080)
493             {
494                 Channels_Positions+=__T(" C");
495                 Count++;
496             }
497             if (channel_mask&0x0002)
498             {
499                 Channels_Positions+=__T(" R");
500                 Count++;
501             }
502             Channels_Positions2+=Ztring::ToZtring(Count);
503         }
504         if (channel_mask&0x0600)
505         {
506             int8u Count=0;
507             if (!Channels_Positions.empty())
508                 Channels_Positions+=__T(", ");
509             Channels_Positions+=__T("Side:");
510             if (channel_mask&0x0200)
511             {
512                 Channels_Positions+=__T(" L");
513                 Count++;
514             }
515             if (channel_mask&0x0400)
516             {
517                 Channels_Positions+=__T(" R");
518                 Count++;
519             }
520             Channels_Positions2+=__T('.')+Ztring::ToZtring(Count);
521         }
522         else
523             Channels_Positions2+=__T("/0");
524         if (channel_mask&0x0130)
525         {
526             int8u Count=0;
527             if (!Channels_Positions.empty())
528                 Channels_Positions+=__T(", ");
529             Channels_Positions+=__T("Back:");
530             if (channel_mask&0x0010)
531             {
532                 Channels_Positions+=__T(" L");
533                 Count++;
534             }
535             if (channel_mask&0x0100)
536             {
537                 Channels_Positions+=__T(" C");
538                 Count++;
539             }
540             if (channel_mask&0x0020)
541             {
542                 Channels_Positions+=__T(" R");
543                 Count++;
544             }
545             Channels_Positions2+=__T('/')+Ztring::ToZtring(Count);
546         }
547         else
548             Channels_Positions2+=__T("/0");
549         if (channel_mask&0x0008)
550         {
551             if (!Channels_Positions.empty())
552                 Channels_Positions+=__T(", ");
553             Channels_Positions+=__T("LFE");
554             Channels_Positions2+=__T(".1");
555         }
556         Fill(Stream_Audio, 0, Audio_ChannelPositions, Channels_Positions);
557         Fill(Stream_Audio, 0, Audio_ChannelPositions_String2, Channels_Positions2);
558         Fill(Stream_Audio, 0, Audio_ChannelLayout, ExtensibleWave_ChannelMask_ChannelLayout(channel_mask));
559     }
560 
561     if (!FromMKV && SamplingRate<15)
562     {
563         Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, Wvpk_SamplingRate[SamplingRate]);
564         if (total_samples_FirstFrame!=(int32u)-1) //--> this is a valid value
565             Fill(Stream_Audio, 0, Audio_Duration, ((int64u)total_samples_FirstFrame)*1000/Wvpk_SamplingRate[SamplingRate]);
566     }
567     Fill(Stream_Audio, 0, Audio_Format_Settings, hybrid?"Hybrid lossy":"Lossless");
568     Fill(Stream_Audio, 0, Audio_Codec_Settings, hybrid?"hybrid lossy":"lossless");
569     Fill(Stream_Audio, 0, Audio_Encoded_Library_Settings, Encoded_Library_Settings);
570 
571     //No more need data
572     File__Tags_Helper::GoToFromEnd(512*1024, "WavPack");
573 }
574 
575 //***************************************************************************
576 // Elements
577 //***************************************************************************
578 
579 //---------------------------------------------------------------------------
id_07()580 void File_Wvpk::id_07()
581 {
582     //Parsing
583     Skip_XX(Size,                                               "Data (Not decoded yet)");
584 
585     FILLING_BEGIN();
586         if (Retrieve(Stream_Audio, 0, Audio_Compression_Mode).empty())
587             Fill(Stream_Audio, 0, Audio_Compression_Mode, "Lossless", Unlimited, true, true);
588     FILLING_END();
589 }
590 
591 //---------------------------------------------------------------------------
id_0D()592 void File_Wvpk::id_0D()
593 {
594     //Parsing
595     Get_L1 (num_channels,                                       "num_channels");
596     switch (Size)
597     {
598         case 1 :
599                     break;
600         case 2 :
601                     {
602                     int8u channel_mask_1;
603                     Get_L1 (channel_mask_1,                     "channel_mask");
604                     channel_mask=channel_mask_1;
605                     }
606                     break;
607         case 3 :
608                     {
609                     int16u channel_mask_2;
610                     Get_L2 (channel_mask_2,                     "channel_mask");
611                     channel_mask=channel_mask_2;
612                     }
613                     break;
614         case 4 :
615                     Get_L3 (channel_mask,                       "channel_mask");
616                     break;
617         case 5 :
618                     Get_L4 (channel_mask,                       "channel_mask");
619                     break;
620         default :   Skip_XX(Size,                               "unknown");
621     }
622 }
623 
624 //---------------------------------------------------------------------------
id_25()625 void File_Wvpk::id_25()
626 {
627     //Parsing
628     int32u flags;
629     int8u  extra=1;
630     Get_L3 (flags,                                              "flags");
631         Skip_Flags(flags,  0,                                   "");
632         Skip_Flags(flags,  1,                                   "fast mode");
633         Skip_Flags(flags,  2,                                   "");
634         Skip_Flags(flags,  3,                                   "high quality mode");
635 
636         Skip_Flags(flags,  4,                                   "very high quality mode");
637         Skip_Flags(flags,  5,                                   "bitrate is kbps, not bits/sample");
638         Skip_Flags(flags,  6,                                   "automatic noise shaping");
639         Skip_Flags(flags,  7,                                   "shaping mode specified");
640 
641         Skip_Flags(flags,  8,                                   "joint-stereo mode specified");
642         Skip_Flags(flags,  9,                                   "dynamic noise shaping");
643         Skip_Flags(flags, 10,                                   "create executable");
644         Skip_Flags(flags, 11,                                   "create correction file");
645 
646         Skip_Flags(flags, 12,                                   "maximize bybrid compression");
647         Skip_Flags(flags, 13,                                   "");
648         Skip_Flags(flags, 14,                                   "");
649         Skip_Flags(flags, 15,                                   "calc noise in hybrid mode");
650 
651         Skip_Flags(flags, 16,                                   "lossy mode");
652         Skip_Flags(flags, 17,                                   "extra processing mode");
653         Skip_Flags(flags, 18,                                   "no wvx stream w/ floats & big ints");
654         Skip_Flags(flags, 19,                                   "store MD5 signature");
655 
656         Skip_Flags(flags, 20,                                   "merge blocks of equal redundancy (for lossyWAV)");
657         Skip_Flags(flags, 21,                                   "");
658         Skip_Flags(flags, 22,                                   "");
659         Skip_Flags(flags, 23,                                   "optimize for mono streams posing as stereo");
660     if (flags&0x20000 && Size>=4)
661     {
662         Get_L1(extra,                                           "extra");
663     }
664 
665     if ((flags&0x20000 && Size>4) || (!(flags&0x20000) && Size>3))
666         Skip_XX(Size-3-(flags&0x20000?1:0),                     "unknown");
667 
668     //Filling
669     if (flags&0x000001)
670         Encoded_Library_Settings+=__T(" -?");
671     if (flags&0x000002)
672         Encoded_Library_Settings+=__T(" -f");
673     if (flags&0x000004)
674         Encoded_Library_Settings+=__T(" -?");
675     if (flags&0x000008)
676         Encoded_Library_Settings+=__T(" -h");
677     if (flags&0x000010)
678         Encoded_Library_Settings+=__T(" -hh");
679     if (flags&0x000020)
680         Encoded_Library_Settings+=__T(" -?(bitrate is kbps, not bits/sample)");
681     if (flags&0x000040)
682         Encoded_Library_Settings+=__T(" -?(automatic noise shaping)");
683     if (flags&0x000080)
684         Encoded_Library_Settings+=__T(" -sn");
685     if (flags&0x000100)
686         Encoded_Library_Settings+=__T(" -jn");
687     if (flags&0x000200)
688         Encoded_Library_Settings+=__T(" -use-dns");
689     if (flags&0x000400)
690         Encoded_Library_Settings+=__T(" -e");
691     if (flags&0x000800)
692         Encoded_Library_Settings+=__T(" -c");
693     if (flags&0x001000)
694         Encoded_Library_Settings+=__T(" -cc");
695     if (flags&0x002000)
696         Encoded_Library_Settings+=__T(" -?");
697     if (flags&0x004000)
698         Encoded_Library_Settings+=__T(" -?");
699     if (flags&0x008000)
700         Encoded_Library_Settings+=__T(" -n");
701     if (flags&0x010000)
702         Encoded_Library_Settings+=__T(" -?(lossy mode)");
703     if (flags&0x020000)
704     {
705         Encoded_Library_Settings+=__T(" -x");
706         if (extra)
707             Encoded_Library_Settings+=Ztring::ToZtring(extra);
708     }
709     if (flags&0x04000)
710         Encoded_Library_Settings+=__T(" -?");
711     if (flags&0x080000)
712         Encoded_Library_Settings+=__T(" -m");
713     if (flags&0x100000)
714         Encoded_Library_Settings+=__T(" --merge-blocks");
715     if (flags&0x200000)
716         Encoded_Library_Settings+=__T(" -?");
717     if (flags&0x400000)
718         Encoded_Library_Settings+=__T(" -?");
719     if (flags&0x800000)
720         Encoded_Library_Settings+=__T(" --optimize-mono");
721     if (!Encoded_Library_Settings.empty())
722         Encoded_Library_Settings.erase(Encoded_Library_Settings.begin());
723 }
724 
725 //***************************************************************************
726 // C++
727 //***************************************************************************
728 
729 } //NameSpace
730 
731 #endif //MEDIAINFO_WVPK_YES
732