| Conditions | 47 |
| Paths | 13 |
| Total Lines | 216 |
| Lines | 16 |
| Ratio | 7.41 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 27 | public function Analyze() { |
||
| 28 | $info = &$this->getid3->info; |
||
| 29 | |||
| 30 | $this->fseek($info['avdataoffset']); |
||
| 31 | $DSDIFFheader = $this->fread(4); |
||
| 32 | |||
| 33 | // https://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf |
||
| 34 | if (substr($DSDIFFheader, 0, 4) != 'FRM8') { |
||
| 35 | $this->error('Expecting "FRM8" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($DSDIFFheader, 0, 4)).'"'); |
||
| 36 | return false; |
||
| 37 | } |
||
| 38 | unset($DSDIFFheader); |
||
| 39 | $this->fseek($info['avdataoffset']); |
||
| 40 | |||
| 41 | $info['encoding'] = 'ISO-8859-1'; // not certain, but assumed |
||
| 42 | $info['fileformat'] = 'dsdiff'; |
||
| 43 | $info['mime_type'] = 'audio/dsd'; |
||
| 44 | $info['audio']['dataformat'] = 'dsdiff'; |
||
| 45 | $info['audio']['bitrate_mode'] = 'cbr'; |
||
| 46 | $info['audio']['bits_per_sample'] = 1; |
||
| 47 | |||
| 48 | $info['dsdiff'] = array(); |
||
| 49 | while (!$this->feof() && ($ChunkHeader = $this->fread(12))) { |
||
| 50 | if (strlen($ChunkHeader) < 12) { |
||
| 51 | $this->error('Expecting chunk header at offset '.(isset($thisChunk['offset']) ? $thisChunk['offset'] : 'N/A').', found insufficient data in file, aborting parsing'); |
||
| 52 | break; |
||
| 53 | } |
||
| 54 | $thisChunk = array(); |
||
| 55 | $thisChunk['offset'] = $this->ftell() - 12; |
||
| 56 | $thisChunk['name'] = substr($ChunkHeader, 0, 4); |
||
| 57 | if (!preg_match('#^[\\x21-\\x7E]+ *$#', $thisChunk['name'])) { |
||
| 58 | // "a concatenation of four printable ASCII characters in the range ' ' (space, 0x20) through '~'(0x7E). Space (0x20) cannot precede printing characters; trailing spaces are allowed." |
||
| 59 | $this->error('Invalid chunk name "'.$thisChunk['name'].'" ('.getid3_lib::PrintHexBytes($thisChunk['name']).') at offset '.$thisChunk['offset'].', aborting parsing'); |
||
| 60 | } |
||
| 61 | $thisChunk['size'] = getid3_lib::BigEndian2Int(substr($ChunkHeader, 4, 8)); |
||
| 62 | $datasize = $thisChunk['size'] + ($thisChunk['size'] % 2); // "If the data is an odd number of bytes in length, a pad byte must be added at the end. The pad byte is not included in ckDataSize." |
||
| 63 | |||
| 64 | switch ($thisChunk['name']) { |
||
| 65 | View Code Duplication | case 'FRM8': |
|
|
|
|||
| 66 | $thisChunk['form_type'] = $this->fread(4); |
||
| 67 | if ($thisChunk['form_type'] != 'DSD ') { |
||
| 68 | $this->error('Expecting "DSD " at offset '.($this->ftell() - 4).', found "'.getid3_lib::PrintHexBytes($thisChunk['form_type']).'", aborting parsing'); |
||
| 69 | break 2; |
||
| 70 | } |
||
| 71 | // do nothing further, prevent skipping subchunks |
||
| 72 | break; |
||
| 73 | View Code Duplication | case 'PROP': // PROPerty chunk |
|
| 74 | $thisChunk['prop_type'] = $this->fread(4); |
||
| 75 | if ($thisChunk['prop_type'] != 'SND ') { |
||
| 76 | $this->error('Expecting "SND " at offset '.($this->ftell() - 4).', found "'.getid3_lib::PrintHexBytes($thisChunk['prop_type']).'", aborting parsing'); |
||
| 77 | break 2; |
||
| 78 | } |
||
| 79 | // do nothing further, prevent skipping subchunks |
||
| 80 | break; |
||
| 81 | case 'DIIN': // eDIted master INformation chunk |
||
| 82 | // do nothing, just prevent skipping subchunks |
||
| 83 | break; |
||
| 84 | |||
| 85 | case 'FVER': // Format VERsion chunk |
||
| 86 | if ($thisChunk['size'] == 4) { |
||
| 87 | $FVER = $this->fread(4); |
||
| 88 | $info['dsdiff']['format_version'] = ord($FVER[0]).'.'.ord($FVER[1]).'.'.ord($FVER[2]).'.'.ord($FVER[3]); |
||
| 89 | unset($FVER); |
||
| 90 | } else { |
||
| 91 | $this->warning('Expecting "FVER" chunk to be 4 bytes, found '.$thisChunk['size'].' bytes, skipping chunk'); |
||
| 92 | $this->fseek($datasize, SEEK_CUR); |
||
| 93 | } |
||
| 94 | break; |
||
| 95 | case 'FS ': // sample rate chunk |
||
| 96 | if ($thisChunk['size'] == 4) { |
||
| 97 | $info['dsdiff']['sample_rate'] = getid3_lib::BigEndian2Int($this->fread(4)); |
||
| 98 | $info['audio']['sample_rate'] = $info['dsdiff']['sample_rate']; |
||
| 99 | } else { |
||
| 100 | $this->warning('Expecting "FVER" chunk to be 4 bytes, found '.$thisChunk['size'].' bytes, skipping chunk'); |
||
| 101 | $this->fseek($datasize, SEEK_CUR); |
||
| 102 | } |
||
| 103 | break; |
||
| 104 | case 'CHNL': // CHaNneLs chunk |
||
| 105 | $thisChunk['num_channels'] = getid3_lib::BigEndian2Int($this->fread(2)); |
||
| 106 | if ($thisChunk['num_channels'] == 0) { |
||
| 107 | $this->warning('channel count should be greater than zero, skipping chunk'); |
||
| 108 | $this->fseek($datasize - 2, SEEK_CUR); |
||
| 109 | } |
||
| 110 | for ($i = 0; $i < $thisChunk['num_channels']; $i++) { |
||
| 111 | $thisChunk['channels'][$i] = $this->fread(4); |
||
| 112 | } |
||
| 113 | $info['audio']['channels'] = $thisChunk['num_channels']; |
||
| 114 | break; |
||
| 115 | case 'CMPR': // CoMPRession type chunk |
||
| 116 | $thisChunk['compression_type'] = $this->fread(4); |
||
| 117 | $info['audio']['dataformat'] = trim($thisChunk['compression_type']); |
||
| 118 | $humanReadableByteLength = getid3_lib::BigEndian2Int($this->fread(1)); |
||
| 119 | $thisChunk['compression_name'] = $this->fread($humanReadableByteLength); |
||
| 120 | if (($humanReadableByteLength % 2) == 0) { |
||
| 121 | // need to seek to multiple of 2 bytes, human-readable string length is only one byte long so if the string is an even number of bytes we need to seek past a padding byte after the string |
||
| 122 | $this->fseek(1, SEEK_CUR); |
||
| 123 | } |
||
| 124 | unset($humanReadableByteLength); |
||
| 125 | break; |
||
| 126 | case 'ABSS': // ABSolute Start time chunk |
||
| 127 | $ABSS = $this->fread(8); |
||
| 128 | $info['dsdiff']['absolute_start_time']['hours'] = getid3_lib::BigEndian2Int(substr($ABSS, 0, 2)); |
||
| 129 | $info['dsdiff']['absolute_start_time']['minutes'] = getid3_lib::BigEndian2Int(substr($ABSS, 2, 1)); |
||
| 130 | $info['dsdiff']['absolute_start_time']['seconds'] = getid3_lib::BigEndian2Int(substr($ABSS, 3, 1)); |
||
| 131 | $info['dsdiff']['absolute_start_time']['samples'] = getid3_lib::BigEndian2Int(substr($ABSS, 4, 4)); |
||
| 132 | unset($ABSS); |
||
| 133 | break; |
||
| 134 | case 'LSCO': // LoudSpeaker COnfiguration chunk |
||
| 135 | // 0 = 2-channel stereo set-up |
||
| 136 | // 3 = 5-channel set-up according to ITU-R BS.775-1 [ITU] |
||
| 137 | // 4 = 6-channel set-up, 5-channel set-up according to ITU-R BS.775-1 [ITU], plus additional Low Frequency Enhancement (LFE) loudspeaker. Also known as "5.1 configuration" |
||
| 138 | // 65535 = Undefined channel set-up |
||
| 139 | $thisChunk['loundspeaker_config_id'] = getid3_lib::BigEndian2Int($this->fread(2)); |
||
| 140 | break; |
||
| 141 | case 'COMT': // COMmenTs chunk |
||
| 142 | $thisChunk['num_comments'] = getid3_lib::BigEndian2Int($this->fread(2)); |
||
| 143 | for ($i = 0; $i < $thisChunk['num_comments']; $i++) { |
||
| 144 | $thisComment = array(); |
||
| 145 | $COMT = $this->fread(14); |
||
| 146 | $thisComment['creation_year'] = getid3_lib::BigEndian2Int(substr($COMT, 0, 2)); |
||
| 147 | $thisComment['creation_month'] = getid3_lib::BigEndian2Int(substr($COMT, 2, 1)); |
||
| 148 | $thisComment['creation_day'] = getid3_lib::BigEndian2Int(substr($COMT, 3, 1)); |
||
| 149 | $thisComment['creation_hour'] = getid3_lib::BigEndian2Int(substr($COMT, 4, 1)); |
||
| 150 | $thisComment['creation_minute'] = getid3_lib::BigEndian2Int(substr($COMT, 5, 1)); |
||
| 151 | $thisComment['comment_type_id'] = getid3_lib::BigEndian2Int(substr($COMT, 6, 2)); |
||
| 152 | $thisComment['comment_ref_id'] = getid3_lib::BigEndian2Int(substr($COMT, 8, 2)); |
||
| 153 | $thisComment['string_length'] = getid3_lib::BigEndian2Int(substr($COMT, 10, 4)); |
||
| 154 | $thisComment['comment_text'] = $this->fread($thisComment['string_length']); |
||
| 155 | if ($thisComment['string_length'] % 2) { |
||
| 156 | // commentText[] is the description of the Comment. This text must be padded with a byte at the end, if needed, to make it an even number of bytes long. This pad byte, if present, is not included in count. |
||
| 157 | $this->fseek(1, SEEK_CUR); |
||
| 158 | } |
||
| 159 | $thisComment['comment_type'] = $this->DSDIFFcmtType($thisComment['comment_type_id']); |
||
| 160 | $thisComment['comment_reference'] = $this->DSDIFFcmtRef($thisComment['comment_type_id'], $thisComment['comment_ref_id']); |
||
| 161 | $thisComment['creation_unix'] = mktime($thisComment['creation_hour'], $thisComment['creation_minute'], 0, $thisComment['creation_month'], $thisComment['creation_day'], $thisComment['creation_year']); |
||
| 162 | $thisChunk['comments'][$i] = $thisComment; |
||
| 163 | |||
| 164 | $commentkey = ($thisComment['comment_reference'] ?: 'comment'); |
||
| 165 | $info['dsdiff']['comments'][$commentkey][] = $thisComment['comment_text']; |
||
| 166 | unset($thisComment); |
||
| 167 | } |
||
| 168 | break; |
||
| 169 | case 'MARK': // MARKer chunk |
||
| 170 | $MARK = $this->fread(22); |
||
| 171 | $thisChunk['marker_hours'] = getid3_lib::BigEndian2Int(substr($MARK, 0, 2)); |
||
| 172 | $thisChunk['marker_minutes'] = getid3_lib::BigEndian2Int(substr($MARK, 2, 1)); |
||
| 173 | $thisChunk['marker_seconds'] = getid3_lib::BigEndian2Int(substr($MARK, 3, 1)); |
||
| 174 | $thisChunk['marker_samples'] = getid3_lib::BigEndian2Int(substr($MARK, 4, 4)); |
||
| 175 | $thisChunk['marker_offset'] = getid3_lib::BigEndian2Int(substr($MARK, 8, 4)); |
||
| 176 | $thisChunk['marker_type_id'] = getid3_lib::BigEndian2Int(substr($MARK, 12, 2)); |
||
| 177 | $thisChunk['marker_channel'] = getid3_lib::BigEndian2Int(substr($MARK, 14, 2)); |
||
| 178 | $thisChunk['marker_flagraw'] = getid3_lib::BigEndian2Int(substr($MARK, 16, 2)); |
||
| 179 | $thisChunk['string_length'] = getid3_lib::BigEndian2Int(substr($MARK, 18, 4)); |
||
| 180 | $thisChunk['description'] = ($thisChunk['string_length'] ? $this->fread($thisChunk['string_length']) : ''); |
||
| 181 | if ($thisChunk['string_length'] % 2) { |
||
| 182 | // markerText[] is the description of the marker. This text must be padded with a byte at the end, if needed, to make it an even number of bytes long. This pad byte, if present, is not included in count. |
||
| 183 | $this->fseek(1, SEEK_CUR); |
||
| 184 | } |
||
| 185 | $thisChunk['marker_type'] = $this->DSDIFFmarkType($thisChunk['marker_type_id']); |
||
| 186 | unset($MARK); |
||
| 187 | break; |
||
| 188 | case 'DIAR': // artist chunk |
||
| 189 | case 'DITI': // title chunk |
||
| 190 | $thisChunk['string_length'] = getid3_lib::BigEndian2Int($this->fread(4)); |
||
| 191 | $thisChunk['description'] = ($thisChunk['string_length'] ? $this->fread($thisChunk['string_length']) : ''); |
||
| 192 | if ($thisChunk['string_length'] % 2) { |
||
| 193 | // This text must be padded with a byte at the end, if needed, to make it an even number of bytes long. This pad byte, if present, is not included in count. |
||
| 194 | $this->fseek(1, SEEK_CUR); |
||
| 195 | } |
||
| 196 | |||
| 197 | if ($commentkey = (($thisChunk['name'] == 'DIAR') ? 'artist' : (($thisChunk['name'] == 'DITI') ? 'title' : ''))) { |
||
| 198 | @$info['dsdiff']['comments'][$commentkey][] = $thisChunk['description']; |
||
| 199 | } |
||
| 200 | break; |
||
| 201 | case 'EMID': // Edited Master ID chunk |
||
| 202 | if ($thisChunk['size']) { |
||
| 203 | $thisChunk['identifier'] = $this->fread($thisChunk['size']); |
||
| 204 | } |
||
| 205 | break; |
||
| 206 | |||
| 207 | case 'ID3 ': |
||
| 208 | $endOfID3v2 = $this->ftell() + $datasize; // we will need to reset the filepointer after parsing ID3v2 |
||
| 209 | |||
| 210 | getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); |
||
| 211 | $getid3_temp = new getID3(); |
||
| 212 | $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); |
||
| 213 | $getid3_id3v2 = new getid3_id3v2($getid3_temp); |
||
| 214 | $getid3_id3v2->StartingOffset = $this->ftell(); |
||
| 215 | if ($thisChunk['valid'] = $getid3_id3v2->Analyze()) { |
||
| 216 | $info['id3v2'] = $getid3_temp->info['id3v2']; |
||
| 217 | } |
||
| 218 | unset($getid3_temp, $getid3_id3v2); |
||
| 219 | |||
| 220 | $this->fseek($endOfID3v2); |
||
| 221 | break; |
||
| 222 | |||
| 223 | case 'DSD ': // DSD sound data chunk |
||
| 224 | case 'DST ': // DST sound data chunk |
||
| 225 | // actual audio data, we're not interested, skip |
||
| 226 | $this->fseek($datasize, SEEK_CUR); |
||
| 227 | break; |
||
| 228 | default: |
||
| 229 | $this->warning('Unhandled chunk "'.$thisChunk['name'].'"'); |
||
| 230 | $this->fseek($datasize, SEEK_CUR); |
||
| 231 | break; |
||
| 232 | } |
||
| 233 | |||
| 234 | @$info['dsdiff']['chunks'][] = $thisChunk; |
||
| 235 | //break; |
||
| 236 | } |
||
| 237 | if (empty($info['audio']['bitrate']) && !empty($info['audio']['channels']) && !empty($info['audio']['sample_rate']) && !empty($info['audio']['bits_per_sample'])) { |
||
| 238 | $info['audio']['bitrate'] = $info['audio']['bits_per_sample'] * $info['audio']['sample_rate'] * $info['audio']['channels']; |
||
| 239 | } |
||
| 240 | |||
| 241 | return true; |
||
| 242 | } |
||
| 243 | |||
| 311 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.