ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
Avr.php
Go to the documentation of this file.
1<?php
2
3namespace GetId3\Module\Audio;
4
7
10// available at http://getid3.sourceforge.net //
11// or http://www.getid3.org //
13// See readme.txt for more details //
15// //
16// module.audio.avr.php //
17// module for analyzing AVR Audio files //
18// dependencies: NONE //
19// ///
21
29class Avr extends BaseHandler
30{
31 public function analyze()
32 {
33 $info = &$this->getid3->info;
34
35 // http://cui.unige.ch/OSG/info/AudioFormats/ap11.html
36 // http://www.btinternet.com/~AnthonyJ/Atari/programming/avr_format.html
37 // offset type length name comments
38 // ---------------------------------------------------------------------
39 // 0 char 4 ID format ID == "2BIT"
40 // 4 char 8 name sample name (unused space filled with 0)
41 // 12 short 1 mono/stereo 0=mono, -1 (0xFFFF)=stereo
42 // With stereo, samples are alternated,
43 // the first voice is the left :
44 // (LRLRLRLRLRLRLRLRLR...)
45 // 14 short 1 resolution 8, 12 or 16 (bits)
46 // 16 short 1 signed or not 0=unsigned, -1 (0xFFFF)=signed
47 // 18 short 1 loop or not 0=no loop, -1 (0xFFFF)=loop on
48 // 20 short 1 MIDI note 0xFFnn, where 0 <= nn <= 127
49 // 0xFFFF means "no MIDI note defined"
50 // 22 byte 1 Replay speed Frequence in the Replay software
51 // 0=5.485 Khz, 1=8.084 Khz, 2=10.971 Khz,
52 // 3=16.168 Khz, 4=21.942 Khz, 5=32.336 Khz
53 // 6=43.885 Khz, 7=47.261 Khz
54 // -1 (0xFF)=no defined Frequence
55 // 23 byte 3 sample rate in Hertz
56 // 26 long 1 size in bytes (2 * bytes in stereo)
57 // 30 long 1 loop begin 0 for no loop
58 // 34 long 1 loop size equal to 'size' for no loop
59 // 38 short 2 Reserved, MIDI keyboard split */
60 // 40 short 2 Reserved, sample compression */
61 // 42 short 2 Reserved */
62 // 44 char 20; Additional filename space, used if (name[7] != 0)
63 // 64 byte 64 user data
64 // 128 bytes ? sample data (12 bits samples are coded on 16 bits:
65 // 0000 xxxx xxxx xxxx)
66 // ---------------------------------------------------------------------
67 // Note that all values are in motorola (big-endian) format, and that long is
68 // assumed to be 4 bytes, and short 2 bytes.
69 // When reading the samples, you should handle both signed and unsigned data,
70 // and be prepared to convert 16->8 bit, or mono->stereo if needed. To convert
71 // 8-bit data between signed/unsigned just add 127 to the sample values.
72 // Simularly for 16-bit data you should add 32769
73
74 $info['fileformat'] = 'avr';
75
76 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
77 $AVRheader = fread($this->getid3->fp, 128);
78
79 $info['avr']['raw']['magic'] = substr($AVRheader, 0, 4);
80 $magic = '2BIT';
81 if ($info['avr']['raw']['magic'] != $magic) {
82 $info['error'][] = 'Expecting "' . Helper::PrintHexBytes($magic) . '" at offset ' . $info['avdataoffset'] . ', found "' . Helper::PrintHexBytes($info['avr']['raw']['magic']) . '"';
83 unset($info['fileformat']);
84 unset($info['avr']);
85
86 return false;
87 }
88 $info['avdataoffset'] += 128;
89
90 $info['avr']['sample_name'] = rtrim(substr($AVRheader, 4, 8));
91 $info['avr']['raw']['mono'] = Helper::BigEndian2Int(substr($AVRheader,
92 12,
93 2));
94 $info['avr']['bits_per_sample'] = Helper::BigEndian2Int(substr($AVRheader,
95 14,
96 2));
97 $info['avr']['raw']['signed'] = Helper::BigEndian2Int(substr($AVRheader,
98 16,
99 2));
100 $info['avr']['raw']['loop'] = Helper::BigEndian2Int(substr($AVRheader,
101 18,
102 2));
103 $info['avr']['raw']['midi'] = Helper::BigEndian2Int(substr($AVRheader,
104 20,
105 2));
106 $info['avr']['raw']['replay_freq'] = Helper::BigEndian2Int(substr($AVRheader,
107 22,
108 1));
109 $info['avr']['sample_rate'] = Helper::BigEndian2Int(substr($AVRheader,
110 23,
111 3));
112 $info['avr']['sample_length'] = Helper::BigEndian2Int(substr($AVRheader,
113 26,
114 4));
115 $info['avr']['loop_start'] = Helper::BigEndian2Int(substr($AVRheader,
116 30,
117 4));
118 $info['avr']['loop_end'] = Helper::BigEndian2Int(substr($AVRheader,
119 34, 4));
120 $info['avr']['midi_split'] = Helper::BigEndian2Int(substr($AVRheader,
121 38,
122 2));
123 $info['avr']['sample_compression'] = Helper::BigEndian2Int(substr($AVRheader,
124 40,
125 2));
126 $info['avr']['reserved'] = Helper::BigEndian2Int(substr($AVRheader,
127 42, 2));
128 $info['avr']['sample_name_extra'] = rtrim(substr($AVRheader, 44, 20));
129 $info['avr']['comment'] = rtrim(substr($AVRheader, 64, 64));
130
131 $info['avr']['flags']['stereo'] = (($info['avr']['raw']['mono'] == 0) ? false : true);
132 $info['avr']['flags']['signed'] = (($info['avr']['raw']['signed'] == 0) ? false : true);
133 $info['avr']['flags']['loop'] = (($info['avr']['raw']['loop'] == 0) ? false : true);
134
135 $info['avr']['midi_notes'] = array();
136 if (($info['avr']['raw']['midi'] & 0xFF00) != 0xFF00) {
137 $info['avr']['midi_notes'][] = ($info['avr']['raw']['midi'] & 0xFF00) >> 8;
138 }
139 if (($info['avr']['raw']['midi'] & 0x00FF) != 0x00FF) {
140 $info['avr']['midi_notes'][] = ($info['avr']['raw']['midi'] & 0x00FF);
141 }
142
143 if (($info['avdataend'] - $info['avdataoffset']) != ($info['avr']['sample_length'] * (($info['avr']['bits_per_sample'] == 8) ? 1 : 2))) {
144 $info['warning'][] = 'Probable truncated file: expecting ' . ($info['avr']['sample_length'] * (($info['avr']['bits_per_sample'] == 8) ? 1 : 2)) . ' bytes of audio data, found ' . ($info['avdataend'] - $info['avdataoffset']);
145 }
146
147 $info['audio']['dataformat'] = 'avr';
148 $info['audio']['lossless'] = true;
149 $info['audio']['bitrate_mode'] = 'cbr';
150 $info['audio']['bits_per_sample'] = $info['avr']['bits_per_sample'];
151 $info['audio']['sample_rate'] = $info['avr']['sample_rate'];
152 $info['audio']['channels'] = ($info['avr']['flags']['stereo'] ? 2 : 1);
153 $info['playtime_seconds'] = ($info['avr']['sample_length'] / $info['audio']['channels']) / $info['avr']['sample_rate'];
154 $info['audio']['bitrate'] = ($info['avr']['sample_length'] * (($info['avr']['bits_per_sample'] == 8) ? 8 : 16)) / $info['playtime_seconds'];
155
156 return true;
157 }
158}
An exception for terminatinating execution or to throw for unit testing.
GetId3() by James Heinrich info@getid3.org //.
Definition: BaseHandler.php:26
fseek($bytes, $whence=SEEK_SET)
GetId3() by James Heinrich info@getid3.org //.
Definition: Helper.php:27
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
Definition: Helper.php:374
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
Definition: Helper.php:36
GetId3() by James Heinrich info@getid3.org //.
Definition: Avr.php:30
analyze()
Analyze from file pointer.
Definition: Avr.php:31
$info
Definition: example_052.php:80