Completed
Push — vendor/getid3 ( d7a1ee...1697a0 )
by Pauli
02:48
created

getid3_dsdiff   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 289
Duplicated Lines 5.54 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 16
loc 289
rs 4.5599
c 0
b 0
f 0
wmc 58
lcom 1
cbo 4

4 Methods

Rating   Name   Duplication   Size   Complexity  
A DSDIFFcmtType() 0 9 2
B DSDIFFcmtRef() 0 28 7
A DSDIFFmarkType() 0 10 2
F Analyze() 16 216 47

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like getid3_dsdiff often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use getid3_dsdiff, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/////////////////////////////////////////////////////////////////
4
/// getID3() by James Heinrich <[email protected]>               //
5
//  available at https://github.com/JamesHeinrich/getID3       //
6
//            or https://www.getid3.org                        //
7
//            or http://getid3.sourceforge.net                 //
8
//  see readme.txt for more details                            //
9
/////////////////////////////////////////////////////////////////
10
//                                                             //
11
// module.audio.dsdiff.php                                     //
12
// module for analyzing Direct Stream Digital Interchange      //
13
// File Format (DSDIFF) files                                  //
14
// dependencies: NONE                                          //
15
//                                                            ///
16
/////////////////////////////////////////////////////////////////
17
18
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
19
	exit;
20
}
21
22
class getid3_dsdiff extends getid3_handler
23
{
24
	/**
25
	 * @return bool
26
	 */
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':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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');
0 ignored issues
show
Security Bug introduced by
It seems like $thisChunk['form_type'] can also be of type false; however, getid3_lib::PrintHexBytes() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
69
						break 2;
70
					}
71
					// do nothing further, prevent skipping subchunks
72
					break;
73 View Code Duplication
				case 'PROP': // PROPerty chunk
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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');
0 ignored issues
show
Security Bug introduced by
It seems like $thisChunk['prop_type'] can also be of type false; however, getid3_lib::PrintHexBytes() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
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));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
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));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(2) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
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));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(1) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
119
					$thisChunk['compression_name'] = $this->fread($humanReadableByteLength);
0 ignored issues
show
Bug introduced by
It seems like $humanReadableByteLength defined by \getid3_lib::BigEndian2Int($this->fread(1)) on line 118 can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
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));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(2) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
140
					break;
141
				case 'COMT': // COMmenTs chunk
142
					$thisChunk['num_comments'] = getid3_lib::BigEndian2Int($this->fread(2));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(2) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
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']);
0 ignored issues
show
Bug introduced by
It seems like $thisComment['string_length'] can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
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']) : '');
0 ignored issues
show
Bug introduced by
It seems like $thisChunk['string_length'] can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
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));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
191
					$thisChunk['description'] = ($thisChunk['string_length'] ? $this->fread($thisChunk['string_length']) : '');
0 ignored issues
show
Bug introduced by
It seems like $thisChunk['string_length'] can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
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'];
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->ftell() can also be of type boolean. However, the property $StartingOffset is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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;
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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
244
	/**
245
	 * @param int $cmtType
246
	 *
247
	 * @return string
248
	 */
249
	public static function DSDIFFcmtType($cmtType) {
250
		static $DSDIFFcmtType = array(
251
			0 => 'General (album) Comment',
252
			1 => 'Channel Comment',
253
			2 => 'Sound Source',
254
			3 => 'File History',
255
		);
256
		return (isset($DSDIFFcmtType[$cmtType]) ? $DSDIFFcmtType[$cmtType] : 'reserved');
257
	}
258
259
	/**
260
	 * @param int $cmtType
261
	 * @param int $cmtRef
262
	 *
263
	 * @return string
264
	 */
265
	public static function DSDIFFcmtRef($cmtType, $cmtRef) {
266
		static $DSDIFFcmtRef = array(
267
			2 => array(  // Sound Source
268
				0 => 'DSD recording',
269
				1 => 'Analogue recording',
270
				2 => 'PCM recording',
271
			),
272
			3 => array( // File History
273
				0 => 'comment',   // General Remark
274
				1 => 'encodeby',  // Name of the operator
275
				2 => 'encoder',   // Name or type of the creating machine
276
				3 => 'timezone',  // Time zone information
277
				4 => 'revision',  // Revision of the file
278
			),
279
		);
280
		switch ($cmtType) {
281
			case 0:
282
				// If the comment type is General Comment the comment reference must be 0
283
				return '';
284
			case 1:
285
				// If the comment type is Channel Comment, the comment reference defines the channel number to which the comment belongs
286
				return ($cmtRef ? 'channel '.$cmtRef : 'all channels');
287
			case 2:
288
			case 3:
289
				return (isset($DSDIFFcmtRef[$cmtType][$cmtRef]) ? $DSDIFFcmtRef[$cmtType][$cmtRef] : 'reserved');
290
		}
291
		return 'unsupported $cmtType='.$cmtType;
292
	}
293
294
	/**
295
	 * @param int $markType
296
	 *
297
	 * @return string
298
	 */
299
	public static function DSDIFFmarkType($markType) {
300
		static $DSDIFFmarkType = array(
301
			0 => 'TrackStart',   // Entry point for a Track start
302
			1 => 'TrackStop',    // Entry point for ending a Track
303
			2 => 'ProgramStart', // Start point of 2-channel or multi-channel area
304
			3 => 'Obsolete',     //
305
			4 => 'Index',        // Entry point of an Index
306
		);
307
		return (isset($DSDIFFmarkType[$markType]) ? $DSDIFFmarkType[$markType] : 'reserved');
308
	}
309
310
}
311