1 : <?php
2 :
3 : /**
4 : * \Midi\Emit\File
5 : *
6 : * @package Midi
7 : * @subpackage Emit
8 : * @copyright © 2009 Tommy Montgomery <http://phpmidiparser.com/>
9 : * @since 1.0
10 : */
11 :
12 : namespace Midi\Emit;
13 :
14 : use \Midi\Util\Timer;
15 : use \Midi\FileHeader;
16 : use \Midi\MidiException;
17 : use \SplFileObject;
18 :
19 : /**
20 : * Represents a MIDI file
21 : *
22 : * @package Midi
23 : * @subpackage Emit
24 : * @since 1.0
25 : */
26 1 : class File {
27 :
28 : /**
29 : * Collection of tracks
30 : *
31 : * @var array
32 : */
33 : private $tracks;
34 :
35 : /**
36 : * @var int
37 : */
38 : private $timeDivision;
39 :
40 : /**
41 : * @var int
42 : */
43 : private $format;
44 :
45 : /**
46 : * Constructor
47 : *
48 : * @since 1.0
49 : */
50 : public function __construct($timeDivision, $format = null) {
51 8 : $this->tracks = array();
52 8 : $this->timeDivision = $timeDivision;
53 8 : $this->format = $format;
54 8 : }
55 :
56 : /**
57 : * Gets the binary data for the MIDI file
58 : *
59 : * @since 1.0
60 : * @uses createFileHeader()
61 : * @uses FileHeader::toBinary()
62 : * @uses Track::getData()
63 : *
64 : * @throws {@link MidiException}
65 : * @return string A binary string
66 : */
67 : public function getData() {
68 4 : $numTracks = count($this->tracks);
69 4 : if ($numTracks === 0) {
70 1 : throw new MidiException('No tracks have been added');
71 : }
72 :
73 3 : if ($this->format === null) {
74 2 : if ($numTracks > 1) {
75 1 : $this->format = 1;
76 1 : } else {
77 1 : $this->format = 0;
78 : }
79 2 : }
80 :
81 3 : if ($this->format === 0 && $numTracks > 1) {
82 1 : throw new MidiException('Cannot have multiple tracks in MIDI format 0');
83 : }
84 :
85 2 : $data = $this->createFileHeader($this->format, $numTracks, $this->timeDivision)->toBinary();
86 2 : foreach ($this->tracks as $track) {
87 2 : $data .= $track->getData();
88 2 : }
89 :
90 2 : return $data;
91 : }
92 :
93 : /**
94 : * Saves the MIDI file to the specified file
95 : *
96 : * @since 1.0
97 : * @uses createFileObject()
98 : * @uses getData()
99 : *
100 : * @param SplFileObject|string $file A file path, or a file object opened in "wb" mode
101 : * @return int The amount of data that was written
102 : */
103 : public function save($file) {
104 1 : if (!($file instanceof SplFileObject)) {
105 1 : $file = $this->createFileObject($file);
106 1 : }
107 :
108 1 : $data = $this->getData();
109 1 : $file->fwrite($data, strlen($data));
110 1 : return strlen($data);
111 : }
112 :
113 : /**
114 : * Creates a file object in "wb" mode suitable for {@link save()}
115 : *
116 : * @since 1.0
117 : *
118 : * @param string $file A file path
119 : * @return SplFileObject
120 : */
121 : public function createFileObject($file) {
122 1 : return new SplFileObject($file, 'wb');
123 : }
124 :
125 : /**
126 : * Creates a file header chunk
127 : *
128 : * @since 1.0
129 : *
130 : * @param int $format The MIDI file format
131 : * @param int $numTracks The number of tracks in the file
132 : * @param int $timeDivision The number of MIDI clock ticks per quarter note
133 : * @return FileHeader
134 : */
135 : public function createFileHeader($format, $numTracks, $timeDivision) {
136 1 : return new FileHeader($format, $numTracks, $timeDivision);
137 : }
138 :
139 : /**
140 : * Gets a timer for the file's time division
141 : *
142 : * @since 1.0
143 : *
144 : * @return Timer
145 : */
146 : public function getTimer() {
147 1 : return new Timer($this->timeDivision);
148 : }
149 :
150 : /**
151 : * Adds a track to the file
152 : *
153 : * @since 1.0
154 : *
155 : * @param Track $track
156 : * @return File A reference to $this
157 : */
158 : public function addTrack(Track $track) {
159 3 : $this->tracks[] = $track;
160 3 : return $this;
161 : }
162 :
163 : }
164 :
|