Changeset 52254 for trunk/src/wp-includes/ID3/module.audio.mp3.php
- Timestamp:
- 11/26/2021 03:04:10 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/ID3/module.audio.mp3.php
r51901 r52254 19 19 } 20 20 21 // number of frames to scan to determine if MPEG-audio sequence is valid22 // Lower this number to 5-20 for faster scanning23 // Increase this number to 50+ for most accurate detection of valid VBR/CBR24 // mpeg-audio streams25 define('GETID3_MP3_VALID_CHECK_FRAMES', 35);26 27 21 28 22 class getid3_mp3 extends getid3_handler … … 37 31 38 32 /** 33 * number of frames to scan to determine if MPEG-audio sequence is valid 34 * Lower this number to 5-20 for faster scanning 35 * Increase this number to 50+ for most accurate detection of valid VBR/CBR mpeg-audio streams 36 * 37 * @var int 38 */ 39 public $mp3_valid_check_frames = 50; 40 41 /** 39 42 * @return bool 40 43 */ … … 56 59 } 57 60 61 $CurrentDataLAMEversionString = null; 58 62 if (((isset($info['id3v2']['headerlength']) && ($info['avdataoffset'] > $info['id3v2']['headerlength'])) || (!isset($info['id3v2']) && ($info['avdataoffset'] > 0) && ($info['avdataoffset'] != $initialOffset)))) { 59 63 … … 122 126 $PossiblyLongerLAMEversion_NewString = substr($PossiblyLongerLAMEversion_String, 0, strspn($PossiblyLongerLAMEversion_String, 'LAME0123456789., (abcdefghijklmnopqrstuvwxyzJFSOND)')); //"LAME3.90.3" "LAME3.87 (beta 1, Sep 27 2000)" "LAME3.88 (beta)" 123 127 if (empty($info['audio']['encoder']) || (strlen($PossiblyLongerLAMEversion_NewString) > strlen($info['audio']['encoder']))) { 128 if (!empty($info['audio']['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version']) && ($info['audio']['encoder'] == $info['mpeg']['audio']['LAME']['short_version'])) { 129 if (preg_match('#^LAME[0-9\\.]+#', $PossiblyLongerLAMEversion_NewString, $matches)) { 130 // "LAME3.100" -> "LAME3.100.1", but avoid including "(alpha)" and similar 131 $info['mpeg']['audio']['LAME']['short_version'] = $matches[0]; 132 } 133 } 124 134 $info['audio']['encoder'] = $PossiblyLongerLAMEversion_NewString; 125 135 } … … 296 306 297 307 if ($info['audio']['bitrate_mode'] == 'cbr') { 298 $encoder_options = strtoupper($info['audio']['bitrate_mode']). ceil($info['audio']['bitrate'] / 1000);308 $encoder_options = strtoupper($info['audio']['bitrate_mode']).round($info['audio']['bitrate'] / 1000); 299 309 } else { 300 310 $encoder_options = strtoupper($info['audio']['bitrate_mode']); … … 489 499 $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray; 490 500 } else { 491 $this-> error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset);501 $this->warning('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset); 492 502 return false; 493 503 } … … 723 733 $thisfile_mpeg_audio_lame['long_version'] = substr($headerstring, $VBRidOffset + 120, 20); 724 734 $thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9); 725 $thisfile_mpeg_audio_lame['numeric_version'] = str_replace('LAME', '', $thisfile_mpeg_audio_lame['short_version']); 726 if (preg_match('#^LAME([0-9\\.a-z]+)#', $thisfile_mpeg_audio_lame['long_version'], $matches)) { 735 736 //$thisfile_mpeg_audio_lame['numeric_version'] = str_replace('LAME', '', $thisfile_mpeg_audio_lame['short_version']); 737 $thisfile_mpeg_audio_lame['numeric_version'] = ''; 738 if (preg_match('#^LAME([0-9\\.a-z]*)#', $thisfile_mpeg_audio_lame['long_version'], $matches)) { 727 739 $thisfile_mpeg_audio_lame['short_version'] = $matches[0]; 728 740 $thisfile_mpeg_audio_lame['numeric_version'] = $matches[1]; 729 741 } 730 foreach (explode('.', $thisfile_mpeg_audio_lame['numeric_version']) as $key => $number) { 731 $thisfile_mpeg_audio_lame['integer_version'][$key] = intval($number); 732 } 733 734 //if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') { 735 if ((($thisfile_mpeg_audio_lame['integer_version'][0] * 1000) + $thisfile_mpeg_audio_lame['integer_version'][1]) >= 3090) { // cannot use string version compare, may have "LAME3.90" or "LAME3.100" -- see https://github.com/JamesHeinrich/getID3/issues/207 736 737 // extra 11 chars are not part of version string when LAMEtag present 738 unset($thisfile_mpeg_audio_lame['long_version']); 739 740 // It the LAME tag was only introduced in LAME v3.90 741 // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933 742 743 // Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html 744 // are assuming a 'Xing' identifier offset of 0x24, which is the case for 745 // MPEG-1 non-mono, but not for other combinations 746 $LAMEtagOffsetContant = $VBRidOffset - 0x24; 747 748 // shortcuts 749 $thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array()); 750 $thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD']; 751 $thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track']; 752 $thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album']; 753 $thisfile_mpeg_audio_lame['raw'] = array(); 754 $thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw']; 755 756 // byte $9B VBR Quality 757 // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications. 758 // Actually overwrites original Xing bytes 759 unset($thisfile_mpeg_audio['VBR_scale']); 760 $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1)); 761 762 // bytes $9C-$A4 Encoder short VersionString 763 $thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9); 764 765 // byte $A5 Info Tag revision + VBR method 766 $LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1)); 767 768 $thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4; 769 $thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F; 770 $thisfile_mpeg_audio_lame['vbr_method'] = self::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']); 771 $thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr' 772 773 // byte $A6 Lowpass filter value 774 $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100; 775 776 // bytes $A7-$AE Replay Gain 777 // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html 778 // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude" 779 if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') { 780 // LAME 3.94a16 and later - 9.23 fixed point 781 // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375 782 $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608); 783 } else { 784 // LAME 3.94a15 and earlier - 32-bit floating point 785 // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15 786 $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4)); 742 if (strlen($thisfile_mpeg_audio_lame['numeric_version']) > 0) { 743 foreach (explode('.', $thisfile_mpeg_audio_lame['numeric_version']) as $key => $number) { 744 $thisfile_mpeg_audio_lame['integer_version'][$key] = intval($number); 787 745 } 788 if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) { 789 unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); 790 } else { 791 $thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); 746 //if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') { 747 if ((($thisfile_mpeg_audio_lame['integer_version'][0] * 1000) + $thisfile_mpeg_audio_lame['integer_version'][1]) >= 3090) { // cannot use string version compare, may have "LAME3.90" or "LAME3.100" -- see https://github.com/JamesHeinrich/getID3/issues/207 748 749 // extra 11 chars are not part of version string when LAMEtag present 750 unset($thisfile_mpeg_audio_lame['long_version']); 751 752 // It the LAME tag was only introduced in LAME v3.90 753 // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933 754 755 // Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html 756 // are assuming a 'Xing' identifier offset of 0x24, which is the case for 757 // MPEG-1 non-mono, but not for other combinations 758 $LAMEtagOffsetContant = $VBRidOffset - 0x24; 759 760 // shortcuts 761 $thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array()); 762 $thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD']; 763 $thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track']; 764 $thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album']; 765 $thisfile_mpeg_audio_lame['raw'] = array(); 766 $thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw']; 767 768 // byte $9B VBR Quality 769 // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications. 770 // Actually overwrites original Xing bytes 771 unset($thisfile_mpeg_audio['VBR_scale']); 772 $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1)); 773 774 // bytes $9C-$A4 Encoder short VersionString 775 $thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9); 776 777 // byte $A5 Info Tag revision + VBR method 778 $LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1)); 779 780 $thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4; 781 $thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F; 782 $thisfile_mpeg_audio_lame['vbr_method'] = self::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']); 783 $thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr' 784 785 // byte $A6 Lowpass filter value 786 $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100; 787 788 // bytes $A7-$AE Replay Gain 789 // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html 790 // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude" 791 if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') { 792 // LAME 3.94a16 and later - 9.23 fixed point 793 // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375 794 $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608); 795 } else { 796 // LAME 3.94a15 and earlier - 32-bit floating point 797 // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15 798 $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4)); 799 } 800 if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) { 801 unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); 802 } else { 803 $thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); 804 } 805 806 $thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2)); 807 $thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2)); 808 809 810 if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) { 811 812 $thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13; 813 $thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10; 814 $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9; 815 $thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF; 816 $thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']); 817 $thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']); 818 $thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']); 819 820 if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { 821 $info['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; 822 } 823 $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator']; 824 $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db']; 825 } else { 826 unset($thisfile_mpeg_audio_lame_RGAD['track']); 827 } 828 if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) { 829 830 $thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13; 831 $thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10; 832 $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9; 833 $thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF; 834 $thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']); 835 $thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']); 836 $thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']); 837 838 if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { 839 $info['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; 840 } 841 $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator']; 842 $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db']; 843 } else { 844 unset($thisfile_mpeg_audio_lame_RGAD['album']); 845 } 846 if (empty($thisfile_mpeg_audio_lame_RGAD)) { 847 unset($thisfile_mpeg_audio_lame['RGAD']); 848 } 849 850 851 // byte $AF Encoding flags + ATH Type 852 $EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1)); 853 $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10); 854 $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20); 855 $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40); 856 $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80); 857 $thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F; 858 859 // byte $B0 if ABR {specified bitrate} else {minimal bitrate} 860 $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1)); 861 if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR) 862 $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; 863 } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR) 864 // ignore 865 } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate 866 $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; 867 } 868 869 // bytes $B1-$B3 Encoder delays 870 $EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3)); 871 $thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12; 872 $thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF; 873 874 // byte $B4 Misc 875 $MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1)); 876 $thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03); 877 $thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2; 878 $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5; 879 $thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6; 880 $thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping']; 881 $thisfile_mpeg_audio_lame['stereo_mode'] = self::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']); 882 $thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality']; 883 $thisfile_mpeg_audio_lame['source_sample_freq'] = self::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']); 884 885 // byte $B5 MP3 Gain 886 $thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true); 887 $thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain']; 888 $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6)); 889 890 // bytes $B6-$B7 Preset and surround info 891 $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2)); 892 // Reserved = ($PresetSurroundBytes & 0xC000); 893 $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800); 894 $thisfile_mpeg_audio_lame['surround_info'] = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']); 895 $thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF); 896 $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame); 897 if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) { 898 $this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org'); 899 } 900 if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) { 901 // this may change if 3.90.4 ever comes out 902 $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3'; 903 } 904 905 // bytes $B8-$BB MusicLength 906 $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4)); 907 $ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']); 908 909 // bytes $BC-$BD MusicCRC 910 $thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2)); 911 912 // bytes $BE-$BF CRC-16 of Info Tag 913 $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2)); 914 915 916 // LAME CBR 917 if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { 918 919 $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; 920 $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']); 921 $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate']; 922 //if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) { 923 // $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min']; 924 //} 925 926 } 927 792 928 } 793 794 $thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2));795 $thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2));796 797 798 if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) {799 800 $thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13;801 $thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10;802 $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9;803 $thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF;804 $thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']);805 $thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']);806 $thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']);807 808 if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) {809 $info['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'];810 }811 $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator'];812 $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db'];813 } else {814 unset($thisfile_mpeg_audio_lame_RGAD['track']);815 }816 if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) {817 818 $thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13;819 $thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10;820 $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9;821 $thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF;822 $thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']);823 $thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']);824 $thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']);825 826 if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) {827 $info['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'];828 }829 $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator'];830 $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db'];831 } else {832 unset($thisfile_mpeg_audio_lame_RGAD['album']);833 }834 if (empty($thisfile_mpeg_audio_lame_RGAD)) {835 unset($thisfile_mpeg_audio_lame['RGAD']);836 }837 838 839 // byte $AF Encoding flags + ATH Type840 $EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1));841 $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10);842 $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20);843 $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40);844 $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80);845 $thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F;846 847 // byte $B0 if ABR {specified bitrate} else {minimal bitrate}848 $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1));849 if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR)850 $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'];851 } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR)852 // ignore853 } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate854 $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'];855 }856 857 // bytes $B1-$B3 Encoder delays858 $EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3));859 $thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12;860 $thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF;861 862 // byte $B4 Misc863 $MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1));864 $thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03);865 $thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2;866 $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5;867 $thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6;868 $thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping'];869 $thisfile_mpeg_audio_lame['stereo_mode'] = self::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']);870 $thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality'];871 $thisfile_mpeg_audio_lame['source_sample_freq'] = self::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']);872 873 // byte $B5 MP3 Gain874 $thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true);875 $thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain'];876 $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6));877 878 // bytes $B6-$B7 Preset and surround info879 $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2));880 // Reserved = ($PresetSurroundBytes & 0xC000);881 $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800);882 $thisfile_mpeg_audio_lame['surround_info'] = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']);883 $thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF);884 $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);885 if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {886 $this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org');887 }888 if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {889 // this may change if 3.90.4 ever comes out890 $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3';891 }892 893 // bytes $B8-$BB MusicLength894 $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4));895 $ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']);896 897 // bytes $BC-$BD MusicCRC898 $thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2));899 900 // bytes $BE-$BF CRC-16 of Info Tag901 $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2));902 903 904 // LAME CBR905 if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) {906 907 $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';908 $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']);909 $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];910 //if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) {911 // $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min'];912 //}913 914 }915 916 929 } 917 930 } … … 1009 1022 if (!$this->RecursiveFrameScanning($offset, $nextframetestoffset, $ScanAsCBR)) { 1010 1023 return false; 1024 } 1025 if (!empty($this->getid3->info['mp3_validity_check_bitrates']) && !empty($thisfile_mpeg_audio['bitrate_mode']) && ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') && !empty($thisfile_mpeg_audio['VBR_bitrate'])) { 1026 // https://github.com/JamesHeinrich/getID3/issues/287 1027 if (count(array_keys($this->getid3->info['mp3_validity_check_bitrates'])) == 1) { 1028 list($cbr_bitrate_in_short_scan) = array_keys($this->getid3->info['mp3_validity_check_bitrates']); 1029 $deviation_cbr_from_header_bitrate = abs($thisfile_mpeg_audio['VBR_bitrate'] - $cbr_bitrate_in_short_scan) / $cbr_bitrate_in_short_scan; 1030 if ($deviation_cbr_from_header_bitrate < 0.01) { 1031 // VBR header bitrate may differ slightly from true bitrate of frames, perhaps accounting for overhead of VBR header frame itself? 1032 // If measured CBR bitrate is within 1% of specified bitrate in VBR header then assume that file is truly CBR 1033 $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; 1034 //$this->warning('VBR header ignored, assuming CBR '.round($cbr_bitrate_in_short_scan / 1000).'kbps based on scan of '.$this->mp3_valid_check_frames.' frames'); 1035 } 1036 } 1037 } 1038 if (isset($this->getid3->info['mp3_validity_check_bitrates'])) { 1039 unset($this->getid3->info['mp3_validity_check_bitrates']); 1011 1040 } 1012 1041 … … 1131 1160 $this->decodeMPEGaudioHeader($offset, $firstframetestarray, false); 1132 1161 1133 for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) { 1134 // check next GETID3_MP3_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch 1162 $info['mp3_validity_check_bitrates'] = array(); 1163 for ($i = 0; $i < $this->mp3_valid_check_frames; $i++) { 1164 // check next (default: 50) frames for validity, to make sure we haven't run across a false synch 1135 1165 if (($nextframetestoffset + 4) >= $info['avdataend']) { 1136 1166 // end of file … … 1140 1170 $nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); 1141 1171 if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) { 1172 getid3_lib::safe_inc($info['mp3_validity_check_bitrates'][$nextframetestarray['mpeg']['audio']['bitrate']]); 1142 1173 if ($ScanAsCBR) { 1143 1174 // force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header … … 1274 1305 $LongMPEGpaddingLookup = array(); 1275 1306 $LongMPEGfrequencyLookup = array(); 1307 $Distribution = array(); 1276 1308 $Distribution['bitrate'] = array(); 1277 1309 $Distribution['frequency'] = array(); … … 1434 1466 $sync_seek_buffer_size = strlen($header); 1435 1467 $SynchSeekOffset = 0; 1468 $SyncSeekAttempts = 0; 1469 $SyncSeekAttemptsMax = 1000; 1470 $FirstFrameThisfileInfo = null; 1436 1471 while ($SynchSeekOffset < $sync_seek_buffer_size) { 1437 1472 if ((($avdataoffset + $SynchSeekOffset) < $info['avdataend']) && !feof($this->getid3->fp)) { … … 1472 1507 } 1473 1508 1474 if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // synch detected 1509 if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // possible synch detected 1510 if (++$SyncSeekAttempts >= $SyncSeekAttemptsMax) { 1511 // https://github.com/JamesHeinrich/getID3/issues/286 1512 // corrupt files claiming to be MP3, with a large number of 0xFF bytes near the beginning, can cause this loop to take a very long time 1513 // should have escape condition to avoid spending too much time scanning a corrupt file 1514 // if a synch's not found within the first 128k bytes, then give up 1515 $this->error('Could not find valid MPEG audio synch after scanning '.$SyncSeekAttempts.' candidate offsets'); 1516 if (isset($info['audio']['bitrate'])) { 1517 unset($info['audio']['bitrate']); 1518 } 1519 if (isset($info['mpeg']['audio'])) { 1520 unset($info['mpeg']['audio']); 1521 } 1522 if (empty($info['mpeg'])) { 1523 unset($info['mpeg']); 1524 } 1525 return false; 1526 } 1475 1527 $FirstFrameAVDataOffset = null; 1476 1528 if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) { … … 1512 1564 $info = $dummy; 1513 1565 $info['avdataoffset'] = $GarbageOffsetEnd; 1514 $this->warning('apparently-valid VBR header not used because could not find '. GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd);1566 $this->warning('apparently-valid VBR header not used because could not find '.$this->mp3_valid_check_frames.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd); 1515 1567 } else { 1516 $this->warning('using data from VBR header even though could not find '. GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')');1568 $this->warning('using data from VBR header even though could not find '.$this->mp3_valid_check_frames.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')'); 1517 1569 } 1518 1570 } … … 1559 1611 for ($current_segment = 0; $current_segment < $max_scan_segments; $current_segment++) { 1560 1612 $frames_scanned_this_segment = 0; 1613 $scan_start_offset = array(); 1561 1614 if ($this->ftell() >= $info['avdataend']) { 1562 1615 break; … … 1888 1941 } 1889 1942 1943 $MPEGrawHeader = array(); 1890 1944 $MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4; 1891 1945 $MPEGrawHeader['version'] = (ord($Header4Bytes[1]) & 0x18) >> 3; // BB
Note: See TracChangeset
for help on using the changeset viewer.