xref: /haiku/src/kits/midi/MidiStore.cpp (revision 81f5654c124bf46fba0fd251f208e2d88d81e1ce)
1 /*
2  * Copyright (c) 2002-2004 Matthijs Hollemans
3  * Copyright (c) 2002 Jerome Leveque
4  * Copyright (c) 2002 Paul Stadler
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <File.h>
26 #include <List.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "MidiDefs.h"
31 #include "MidiStore.h"
32 #include "debug.h"
33 
34 //------------------------------------------------------------------------------
35 
36 struct BMidiEvent
37 {
38 	BMidiEvent()
39 	{
40 		byte1  = 0;
41 		byte2  = 0;
42 		byte3  = 0;
43 		data   = NULL;
44 		length = 0;
45 	}
46 
47 	~BMidiEvent()
48 	{
49 		free(data);
50 	}
51 
52 	uint32 time;    // either ticks or milliseconds
53 	bool   ticks;   // event is from MIDI file
54 	uchar  byte1;
55 	uchar  byte2;
56 	uchar  byte3;
57 	void*  data;    // sysex data
58 	size_t length;  // sysex data size
59 	int32  tempo;   // beats per minute
60 };
61 
62 //------------------------------------------------------------------------------
63 
64 static int compare_events(const void* event1, const void* event2)
65 {
66 	BMidiEvent* e1 = *((BMidiEvent**) event1);
67 	BMidiEvent* e2 = *((BMidiEvent**) event2);
68 
69 	return (e1->time - e2->time);
70 }
71 
72 //------------------------------------------------------------------------------
73 
74 BMidiStore::BMidiStore()
75 {
76 	events = new BList;
77 	currentEvent = 0;
78 	startTime = 0;
79 	needsSorting = false;
80 	beatsPerMinute = 60;
81 	ticksPerBeat = 240;
82 	file = NULL;
83 	hookFunc = NULL;
84 	looping = false;
85 	paused = false;
86 	finished = false;
87 	instruments = new bool[128];
88 }
89 
90 //------------------------------------------------------------------------------
91 
92 BMidiStore::~BMidiStore()
93 {
94 	for (int32 t = 0; t < events->CountItems(); ++t)
95 	{
96 		delete EventAt(t);
97 	}
98 	delete events;
99 	delete[] instruments;
100 }
101 
102 //------------------------------------------------------------------------------
103 
104 void BMidiStore::NoteOff(
105 	uchar channel, uchar note, uchar velocity, uint32 time)
106 {
107 	BMidiEvent* event = new BMidiEvent;
108 	event->time  = time;
109 	event->ticks = false;
110 	event->byte1 = B_NOTE_OFF | (channel - 1);
111 	event->byte2 = note;
112 	event->byte3 = velocity;
113 	AddEvent(event);
114 }
115 
116 //------------------------------------------------------------------------------
117 
118 void BMidiStore::NoteOn(
119 	uchar channel, uchar note, uchar velocity, uint32 time)
120 {
121 	BMidiEvent* event = new BMidiEvent;
122 	event->time  = time;
123 	event->ticks = false;
124 	event->byte1 = B_NOTE_ON | (channel - 1);
125 	event->byte2 = note;
126 	event->byte3 = velocity;
127 	AddEvent(event);
128 }
129 
130 //------------------------------------------------------------------------------
131 
132 void BMidiStore::KeyPressure(
133 	uchar channel, uchar note, uchar pressure, uint32 time)
134 {
135 	BMidiEvent* event = new BMidiEvent;
136 	event->time  = time;
137 	event->ticks = false;
138 	event->byte1 = B_KEY_PRESSURE | (channel - 1);
139 	event->byte2 = note;
140 	event->byte3 = pressure;
141 	AddEvent(event);
142 }
143 
144 //------------------------------------------------------------------------------
145 
146 void BMidiStore::ControlChange(
147 	uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
148 {
149 	BMidiEvent* event = new BMidiEvent;
150 	event->time  = time;
151 	event->ticks = false;
152 	event->byte1 = B_CONTROL_CHANGE | (channel - 1);
153 	event->byte2 = controlNumber;
154 	event->byte3 = controlValue;
155 	AddEvent(event);
156 }
157 
158 //------------------------------------------------------------------------------
159 
160 void BMidiStore::ProgramChange(
161 	uchar channel, uchar programNumber, uint32 time)
162 {
163 	BMidiEvent* event = new BMidiEvent;
164 	event->time  = time;
165 	event->ticks = false;
166 	event->byte1 = B_PROGRAM_CHANGE | (channel - 1);
167 	event->byte2 = programNumber;
168 	AddEvent(event);
169 }
170 
171 //------------------------------------------------------------------------------
172 
173 void BMidiStore::ChannelPressure(uchar channel, uchar pressure, uint32 time)
174 {
175 	BMidiEvent* event = new BMidiEvent;
176 	event->time  = time;
177 	event->ticks = false;
178 	event->byte1 = B_CHANNEL_PRESSURE | (channel - 1);
179 	event->byte2 = pressure;
180 	AddEvent(event);
181 }
182 
183 //------------------------------------------------------------------------------
184 
185 void BMidiStore::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
186 {
187 	BMidiEvent* event = new BMidiEvent;
188 	event->time  = time;
189 	event->ticks = false;
190 	event->byte1 = B_PITCH_BEND | (channel - 1);
191 	event->byte2 = lsb;
192 	event->byte3 = msb;
193 	AddEvent(event);
194 }
195 
196 //------------------------------------------------------------------------------
197 
198 void BMidiStore::SystemExclusive(void* data, size_t length, uint32 time)
199 {
200 	BMidiEvent* event = new BMidiEvent;
201 	event->time   = time;
202 	event->ticks  = false;
203 	event->byte1  = B_SYS_EX_START;
204 	event->data   = malloc(length);
205 	event->length = length;
206 	memcpy(event->data, data, length);
207 	AddEvent(event);
208 }
209 
210 //------------------------------------------------------------------------------
211 
212 void BMidiStore::SystemCommon(
213 	uchar status, uchar data1, uchar data2, uint32 time)
214 {
215 	BMidiEvent* event = new BMidiEvent;
216 	event->time  = time;
217 	event->ticks = false;
218 	event->byte1 = status;
219 	event->byte2 = data1;
220 	event->byte3 = data2;
221 	AddEvent(event);
222 }
223 
224 //------------------------------------------------------------------------------
225 
226 void BMidiStore::SystemRealTime(uchar status, uint32 time)
227 {
228 	BMidiEvent* event = new BMidiEvent;
229 	event->time  = time;
230 	event->ticks = false;
231 	event->byte1 = status;
232 	AddEvent(event);
233 }
234 
235 //------------------------------------------------------------------------------
236 
237 void BMidiStore::TempoChange(int32 beatsPerMinute, uint32 time)
238 {
239 	BMidiEvent* event = new BMidiEvent;
240 	event->time  = time;
241 	event->ticks = false;
242 	event->byte1 = 0xFF;
243 	event->byte2 = 0x51;
244 	event->byte3 = 0x03;
245 	event->tempo = beatsPerMinute;
246 	AddEvent(event);
247 }
248 
249 //------------------------------------------------------------------------------
250 
251 status_t BMidiStore::Import(const entry_ref* ref)
252 {
253 	memset(instruments, 0, 128 * sizeof(bool));
254 
255 	try
256 	{
257 		file = new BFile(ref, B_READ_ONLY);
258 		if (file->InitCheck() != B_OK)
259 		{
260 			throw file->InitCheck();
261 		}
262 
263 		char fourcc[4];
264 		ReadFourCC(fourcc);
265 		if (strncmp(fourcc, "MThd", 4) != 0)
266 		{
267 			throw (status_t) B_BAD_MIDI_DATA;
268 		}
269 
270 		if (Read32Bit() != 6)
271 		{
272 			throw (status_t) B_BAD_MIDI_DATA;
273 		}
274 
275 		format = Read16Bit();
276 		numTracks = Read16Bit();
277 		ticksPerBeat = Read16Bit();
278 
279 		if (ticksPerBeat & 0x8000)  // we don't support SMPTE
280 		{                           // time codes, only ticks
281 			ticksPerBeat = 240;     // per quarter note
282 		}
283 
284 		currTrack = 0;
285 		while (currTrack < numTracks)
286 		{
287 			ReadChunk();
288 		}
289 	}
290 	catch (status_t e)
291 	{
292 		delete file;
293 		file = NULL;
294 		return e;
295 	}
296 
297 	SortEvents(true);
298 
299 	delete file;
300 	file = NULL;
301 	return B_OK;
302 }
303 
304 //------------------------------------------------------------------------------
305 
306 status_t BMidiStore::Export(const entry_ref* ref, int32 format)
307 {
308 	try
309 	{
310 		file = new BFile(ref, B_READ_WRITE);
311 		if (file->InitCheck() != B_OK)
312 		{
313 			throw file->InitCheck();
314 		}
315 
316 		SortEvents(true);
317 
318 		WriteFourCC('M', 'T', 'h', 'd');
319 		Write32Bit(6);
320 		Write16Bit(0);  // we do only format 0
321 		Write16Bit(1);
322 		Write16Bit(ticksPerBeat);
323 
324 		WriteTrack();
325 	}
326 	catch (status_t e)
327 	{
328 		delete file;
329 		file = NULL;
330 		return e;
331 	}
332 
333 	delete file;
334 	file = NULL;
335 	return B_OK;
336 }
337 
338 //------------------------------------------------------------------------------
339 
340 void BMidiStore::SortEvents(bool force)
341 {
342 	if (force || needsSorting)
343 	{
344 		events->SortItems(compare_events);
345 		needsSorting = false;
346 	}
347 }
348 
349 //------------------------------------------------------------------------------
350 
351 uint32 BMidiStore::CountEvents() const
352 {
353 	return events->CountItems();
354 }
355 
356 //------------------------------------------------------------------------------
357 
358 uint32 BMidiStore::CurrentEvent() const
359 {
360 	return currentEvent;
361 }
362 
363 //------------------------------------------------------------------------------
364 
365 void BMidiStore::SetCurrentEvent(uint32 eventNumber)
366 {
367 	currentEvent = eventNumber;
368 }
369 
370 //------------------------------------------------------------------------------
371 
372 uint32 BMidiStore::DeltaOfEvent(uint32 eventNumber) const
373 {
374 	// Even though the BeBook says that the delta is the time span between
375 	// an event and the first event in the list, this doesn't appear to be
376 	// true for events that were captured from other BMidi objects such as
377 	// BMidiPort. For those events, we return the absolute timestamp. The
378 	// BeBook is correct for events from MIDI files, though.
379 
380 	BMidiEvent* event = EventAt(eventNumber);
381 	if (event != NULL)
382 	{
383 		return GetEventTime(event);
384 	}
385 
386 	return 0;
387 }
388 
389 //------------------------------------------------------------------------------
390 
391 uint32 BMidiStore::EventAtDelta(uint32 time) const
392 {
393 	for (int32 t = 0; t < events->CountItems(); ++t)
394 	{
395 		if (GetEventTime(EventAt(t)) >= time) { return t; }
396 	}
397 
398 	return 0;
399 }
400 
401 //------------------------------------------------------------------------------
402 
403 uint32 BMidiStore::BeginTime() const
404 {
405 	return startTime;
406 }
407 
408 //------------------------------------------------------------------------------
409 
410 void BMidiStore::SetTempo(int32 beatsPerMinute_)
411 {
412 	beatsPerMinute = beatsPerMinute_;
413 }
414 
415 //------------------------------------------------------------------------------
416 
417 int32 BMidiStore::Tempo() const
418 {
419 	return beatsPerMinute;
420 }
421 
422 //------------------------------------------------------------------------------
423 
424 void BMidiStore::_ReservedMidiStore1() { }
425 void BMidiStore::_ReservedMidiStore2() { }
426 void BMidiStore::_ReservedMidiStore3() { }
427 
428 //------------------------------------------------------------------------------
429 
430 void BMidiStore::Run()
431 {
432 	// This rather compilicated Run() loop is not only used by BMidiStore
433 	// but also by BMidiSynthFile. The "paused", "finished", and "looping"
434 	// flags, and the "stop hook" are especially provided for the latter.
435 
436 	paused = false;
437 	finished = false;
438 
439 	int32 timeAdjust;
440 	uint32 baseTime;
441 	bool firstEvent = true;
442 	bool resetTime = false;
443 
444 	while (KeepRunning())
445 	{
446 		if (paused)
447 		{
448 			resetTime = true;
449 			snooze(100000);
450 			continue;
451 		}
452 
453 		BMidiEvent* event = EventAt(currentEvent);
454 
455 		if (event == NULL)  // no more events
456 		{
457 			if (looping)
458 			{
459 				resetTime = true;
460 				currentEvent = 0;
461 			}
462 			else
463 			{
464 				break;
465 			}
466 		}
467 
468 		if (firstEvent)
469 		{
470 			startTime = B_NOW;
471 			baseTime = startTime;
472 		}
473 		else if (resetTime)
474 		{
475 			baseTime = B_NOW;
476 		}
477 
478 		if (firstEvent || resetTime)
479 		{
480 			timeAdjust = baseTime - GetEventTime(event);
481 			SprayEvent(event, baseTime);
482 			firstEvent = false;
483 			resetTime = false;
484 		}
485 		else
486 		{
487 			SprayEvent(event, GetEventTime(event) + timeAdjust);
488 		}
489 
490 		++currentEvent;
491 	}
492 
493 	finished = true;
494 	paused = false;
495 
496 	if (hookFunc != NULL)
497 	{
498 		(*hookFunc)(hookArg);
499 	}
500 }
501 
502 //------------------------------------------------------------------------------
503 
504 void BMidiStore::AddEvent(BMidiEvent* event)
505 {
506 	events->AddItem(event);
507 	needsSorting = true;
508 }
509 
510 //------------------------------------------------------------------------------
511 
512 void BMidiStore::SprayEvent(const BMidiEvent* event, uint32 time)
513 {
514 	uchar byte1 = event->byte1;
515 	uchar byte2 = event->byte2;
516 	uchar byte3 = event->byte3;
517 
518 	switch (byte1 & 0xF0)
519 	{
520 		case B_NOTE_OFF:
521 			SprayNoteOff((byte1 & 0x0F) + 1, byte2, byte3, time);
522 			return;
523 
524 		case B_NOTE_ON:
525 			SprayNoteOn((byte1 & 0x0F) + 1, byte2, byte3, time);
526 			return;
527 
528 		case B_KEY_PRESSURE:
529 			SprayKeyPressure((byte1 & 0x0F) + 1, byte2, byte3, time);
530 			return;
531 
532 		case B_CONTROL_CHANGE:
533 			SprayControlChange((byte1 & 0x0F) + 1, byte2, byte3, time);
534 			return;
535 
536 		case B_PROGRAM_CHANGE:
537 			SprayProgramChange((byte1 & 0x0F) + 1, byte2, time);
538 			return;
539 
540 		case B_CHANNEL_PRESSURE:
541 			SprayChannelPressure((byte1 & 0x0F) + 1, byte2, time);
542 			return;
543 
544 		case B_PITCH_BEND:
545 			SprayPitchBend((byte1 & 0x0F) + 1, byte2, byte3, time);
546 			return;
547 
548 		case 0xF0:
549 			switch (byte1)
550 			{
551 				case B_SYS_EX_START:
552 					SpraySystemExclusive(event->data, event->length, time);
553 					return;
554 
555 				case B_MIDI_TIME_CODE:
556 				case B_SONG_POSITION:
557 				case B_SONG_SELECT:
558 				case B_CABLE_MESSAGE:
559 				case B_TUNE_REQUEST:
560 				case B_SYS_EX_END:
561 					SpraySystemCommon(byte1, byte2, byte3, time);
562 					return;
563 
564 				case B_TIMING_CLOCK:
565 				case B_START:
566 				case B_CONTINUE:
567 				case B_STOP:
568 				case B_ACTIVE_SENSING:
569 					SpraySystemRealTime(byte1, time);
570 					return;
571 
572 				case B_SYSTEM_RESET:
573 					if ((byte2 == 0x51) && (byte3 == 0x03))
574 					{
575 						SprayTempoChange(event->tempo, time);
576 						beatsPerMinute = event->tempo;
577 					}
578 					else
579 					{
580 						SpraySystemRealTime(byte1, time);
581 					}
582 					return;
583 			}
584 			return;
585 	}
586 }
587 
588 //------------------------------------------------------------------------------
589 
590 BMidiEvent* BMidiStore::EventAt(int32 index) const
591 {
592 	return (BMidiEvent*) events->ItemAt(index);
593 }
594 
595 //------------------------------------------------------------------------------
596 
597 uint32 BMidiStore::GetEventTime(const BMidiEvent* event) const
598 {
599 	if (event->ticks)
600 	{
601 		return TicksToMilliseconds(event->time);
602 	}
603 	else
604 	{
605 		return event->time;
606 	}
607 }
608 
609 //------------------------------------------------------------------------------
610 
611 uint32 BMidiStore::TicksToMilliseconds(uint32 ticks) const
612 {
613 	return ((uint64) ticks * 60000) / (beatsPerMinute * ticksPerBeat);
614 }
615 
616 //------------------------------------------------------------------------------
617 
618 uint32 BMidiStore::MillisecondsToTicks(uint32 ms) const
619 {
620 	return ((uint64) ms * beatsPerMinute * ticksPerBeat) / 60000;
621 }
622 
623 //------------------------------------------------------------------------------
624 
625 void BMidiStore::ReadFourCC(char* fourcc)
626 {
627 	if (file->Read(fourcc, 4) != 4)
628 	{
629 		throw (status_t) B_BAD_MIDI_DATA;
630 	}
631 }
632 
633 //------------------------------------------------------------------------------
634 
635 void BMidiStore::WriteFourCC(char a, char b, char c, char d)
636 {
637 	char fourcc[4] = { a, b, c, d };
638 	if (file->Write(fourcc, 4) != 4)
639 	{
640 		throw (status_t) B_ERROR;
641 	}
642 }
643 
644 //------------------------------------------------------------------------------
645 
646 uint32 BMidiStore::Read32Bit()
647 {
648 	uint8 buf[4];
649 	if (file->Read(buf, 4) != 4)
650 	{
651 		throw (status_t) B_BAD_MIDI_DATA;
652 	}
653 
654 	return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
655 }
656 
657 //------------------------------------------------------------------------------
658 
659 void BMidiStore::Write32Bit(uint32 val)
660 {
661 	uint8 buf[4];
662 	buf[0] = (val >> 24) & 0xFF;
663 	buf[1] = (val >> 16) & 0xFF;
664 	buf[2] = (val >>  8) & 0xFF;
665 	buf[3] =  val        & 0xFF;
666 
667 	if (file->Write(buf, 4) != 4)
668 	{
669 		throw (status_t) B_ERROR;
670 	}
671 }
672 
673 //------------------------------------------------------------------------------
674 
675 uint16 BMidiStore::Read16Bit()
676 {
677 	uint8 buf[2];
678 	if (file->Read(buf, 2) != 2)
679 	{
680 		throw (status_t) B_BAD_MIDI_DATA;
681 	}
682 
683 	return (buf[0] << 8) | buf[1];
684 }
685 
686 //------------------------------------------------------------------------------
687 
688 void BMidiStore::Write16Bit(uint16 val)
689 {
690 	uint8 buf[2];
691 	buf[0] = (val >>  8) & 0xFF;
692 	buf[1] =  val        & 0xFF;
693 
694 	if (file->Write(buf, 2) != 2)
695 	{
696 		throw (status_t) B_ERROR;
697 	}
698 }
699 
700 //------------------------------------------------------------------------------
701 
702 uint8 BMidiStore::PeekByte()
703 {
704 	uint8 buf;
705 	if (file->Read(&buf, 1) != 1)
706 	{
707 		throw (status_t) B_BAD_MIDI_DATA;
708 	}
709 
710 	if (file->Seek(-1, SEEK_CUR) < 0)
711 	{
712 		throw (status_t) B_ERROR;
713 	}
714 
715 	return buf;
716 }
717 
718 //------------------------------------------------------------------------------
719 
720 uint8 BMidiStore::NextByte()
721 {
722 	uint8 buf;
723 	if (file->Read(&buf, 1) != 1)
724 	{
725 		throw (status_t) B_BAD_MIDI_DATA;
726 	}
727 
728 	--byteCount;
729 	return buf;
730 }
731 
732 //------------------------------------------------------------------------------
733 
734 void BMidiStore::WriteByte(uint8 val)
735 {
736 	if (file->Write(&val, 1) != 1)
737 	{
738 		throw (status_t) B_ERROR;
739 	}
740 
741 	++byteCount;
742 }
743 
744 //------------------------------------------------------------------------------
745 
746 void BMidiStore::SkipBytes(uint32 length)
747 {
748 	if (file->Seek(length, SEEK_CUR) < 0)
749 	{
750 		throw (status_t) B_BAD_MIDI_DATA;
751 	}
752 
753 	byteCount -= length;
754 }
755 
756 //------------------------------------------------------------------------------
757 
758 uint32 BMidiStore::ReadVarLength()
759 {
760 	uint32 val;
761 	uint8 byte;
762 
763 	if ((val = NextByte()) & 0x80)
764 	{
765 		val &= 0x7F;
766 		do
767 		{
768 			val = (val << 7) + ((byte = NextByte()) & 0x7F);
769 		}
770 		while (byte & 0x80);
771 	}
772 
773 	return val;
774 }
775 
776 //------------------------------------------------------------------------------
777 
778 void BMidiStore::WriteVarLength(uint32 val)
779 {
780 	uint32 buffer = val & 0x7F;
781 
782 	while ((val >>= 7))
783 	{
784 		buffer <<= 8;
785 		buffer |= ((val & 0x7F) | 0x80);
786 	}
787 
788 	while (true)
789 	{
790 		WriteByte(buffer);
791 		if (buffer & 0x80)
792 			buffer >>= 8;
793 		else
794 			break;
795 	}
796 }
797 
798 //------------------------------------------------------------------------------
799 
800 void BMidiStore::ReadChunk()
801 {
802 	char fourcc[4];
803 	ReadFourCC(fourcc);
804 
805 	byteCount = Read32Bit();
806 
807 	if (strncmp(fourcc, "MTrk", 4) == 0)
808 	{
809 		ReadTrack();
810 	}
811 	else
812 	{
813 		TRACE(("Skipping '%c%c%c%c' chunk (%lu bytes)",
814 			fourcc[0], fourcc[1], fourcc[2], fourcc[3], byteCount))
815 
816 		SkipBytes(byteCount);
817 	}
818 }
819 
820 //------------------------------------------------------------------------------
821 
822 void BMidiStore::ReadTrack()
823 {
824 	uint8 status = 0;
825 	uint8 data1;
826 	uint8 data2;
827 	BMidiEvent* event;
828 
829 	totalTicks = 0;
830 
831 	while (byteCount > 0)
832 	{
833 		uint32 ticks = ReadVarLength();
834 		totalTicks += ticks;
835 
836 		if (PeekByte() & 0x80)
837 		{
838 			status = NextByte();
839 		}
840 
841 		switch (status & 0xF0)
842 		{
843 			case B_NOTE_OFF:
844 			case B_NOTE_ON:
845 			case B_KEY_PRESSURE:
846 			case B_CONTROL_CHANGE:
847 			case B_PITCH_BEND:
848 				data1 = NextByte();
849 				data2 = NextByte();
850 				event = new BMidiEvent;
851 				event->time  = totalTicks;
852 				event->ticks = true;
853 				event->byte1 = status;
854 				event->byte2 = data1;
855 				event->byte3 = data2;
856 				AddEvent(event);
857 				break;
858 
859 			case B_PROGRAM_CHANGE:
860 			case B_CHANNEL_PRESSURE:
861 				data1 = NextByte();
862 				event = new BMidiEvent;
863 				event->time  = totalTicks;
864 				event->ticks = true;
865 				event->byte1 = status;
866 				event->byte2 = data1;
867 				AddEvent(event);
868 
869 				if ((status & 0xF0) == B_PROGRAM_CHANGE)
870 				{
871 					instruments[data1] = true;
872 				}
873 				break;
874 
875 			case 0xF0:
876 				switch (status)
877 				{
878 					case B_SYS_EX_START:
879 						ReadSystemExclusive();
880 						break;
881 
882 					case B_TUNE_REQUEST:
883 					case B_SYS_EX_END:
884 					case B_TIMING_CLOCK:
885 					case B_START:
886 					case B_CONTINUE:
887 					case B_STOP:
888 					case B_ACTIVE_SENSING:
889 						event = new BMidiEvent;
890 						event->time  = totalTicks;
891 						event->ticks = true;
892 						event->byte1 = status;
893 						AddEvent(event);
894 						break;
895 
896 					case B_MIDI_TIME_CODE:
897 					case B_SONG_SELECT:
898 					case B_CABLE_MESSAGE:
899 						data1 = NextByte();
900 						event = new BMidiEvent;
901 						event->time  = totalTicks;
902 						event->ticks = true;
903 						event->byte1 = status;
904 						event->byte2 = data1;
905 						AddEvent(event);
906 						break;
907 
908 					case B_SONG_POSITION:
909 						data1 = NextByte();
910 						data2 = NextByte();
911 						event = new BMidiEvent;
912 						event->time  = totalTicks;
913 						event->ticks = true;
914 						event->byte1 = status;
915 						event->byte2 = data1;
916 						event->byte3 = data2;
917 						AddEvent(event);
918 						break;
919 
920 					case B_SYSTEM_RESET:
921 						ReadMetaEvent();
922 						break;
923 				}
924 				break;
925 		}
926 
927 		event = NULL;
928 	}
929 
930 	++currTrack;
931 }
932 
933 //------------------------------------------------------------------------------
934 
935 void BMidiStore::ReadSystemExclusive()
936 {
937 	// We do not import sysex's from MIDI files.
938 
939 	SkipBytes(ReadVarLength());
940 }
941 
942 //------------------------------------------------------------------------------
943 
944 void BMidiStore::ReadMetaEvent()
945 {
946 	// We only import the Tempo Change meta event.
947 
948 	uint8 type = NextByte();
949 	uint32 length = ReadVarLength();
950 
951 	if ((type == 0x51) && (length == 3))
952 	{
953 		uchar data[3];
954 		data[0] = NextByte();
955 		data[1] = NextByte();
956 		data[2] = NextByte();
957 		uint32 val = (data[0] << 16) | (data[1] << 8) | data[2];
958 
959 		BMidiEvent* event = new BMidiEvent;
960 		event->time  = totalTicks;
961 		event->ticks = true;
962 		event->byte1 = 0xFF;
963 		event->byte2 = 0x51;
964 		event->byte3 = 0x03;
965 		event->tempo = 60000000 / val;
966 		AddEvent(event);
967 	}
968 	else
969 	{
970 		SkipBytes(length);
971 	}
972 }
973 
974 //------------------------------------------------------------------------------
975 
976 void BMidiStore::WriteTrack()
977 {
978 	WriteFourCC('M', 'T', 'r', 'k');
979 	off_t lengthPos = file->Position();
980 	Write32Bit(0);
981 
982 	byteCount = 0;
983 	uint32 oldTime;
984 	uint32 newTime;
985 
986 	for (uint32 t = 0; t < CountEvents(); ++t)
987 	{
988 		BMidiEvent* event = EventAt(t);
989 
990 		if (event->ticks)
991 		{
992 			newTime = event->time;
993 		}
994 		else
995 		{
996 			newTime = MillisecondsToTicks(event->time);
997 		}
998 
999 		if (t == 0)
1000 		{
1001 			WriteVarLength(0);
1002 		}
1003 		else
1004 		{
1005 			WriteVarLength(newTime - oldTime);
1006 		}
1007 
1008 		oldTime = newTime;
1009 
1010 		switch (event->byte1 & 0xF0)
1011 		{
1012 			case B_NOTE_OFF:
1013 			case B_NOTE_ON:
1014 			case B_KEY_PRESSURE:
1015 			case B_CONTROL_CHANGE:
1016 			case B_PITCH_BEND:
1017 				WriteByte(event->byte1);
1018 				WriteByte(event->byte2);
1019 				WriteByte(event->byte3);
1020 				break;
1021 
1022 			case B_PROGRAM_CHANGE:
1023 			case B_CHANNEL_PRESSURE:
1024 				WriteByte(event->byte1);
1025 				WriteByte(event->byte2);
1026 				break;
1027 
1028 			case 0xF0:
1029 				switch (event->byte1)
1030 				{
1031 					case B_SYS_EX_START:
1032 						// We do not export sysex's.
1033 						break;
1034 
1035 					case B_TUNE_REQUEST:
1036 					case B_SYS_EX_END:
1037 					case B_TIMING_CLOCK:
1038 					case B_START:
1039 					case B_CONTINUE:
1040 					case B_STOP:
1041 					case B_ACTIVE_SENSING:
1042 						WriteByte(event->byte1);
1043 						break;
1044 
1045 					case B_MIDI_TIME_CODE:
1046 					case B_SONG_SELECT:
1047 					case B_CABLE_MESSAGE:
1048 						WriteByte(event->byte1);
1049 						WriteByte(event->byte2);
1050 						break;
1051 
1052 					case B_SONG_POSITION:
1053 						WriteByte(event->byte1);
1054 						WriteByte(event->byte2);
1055 						WriteByte(event->byte3);
1056 						break;
1057 
1058 					case B_SYSTEM_RESET:
1059 						WriteMetaEvent(event);
1060 						break;
1061 				}
1062 				break;
1063 
1064 		}
1065 	}
1066 
1067 	WriteVarLength(0);
1068 	WriteByte(0xFF);   // the end-of-track
1069 	WriteByte(0x2F);   // marker is required
1070 	WriteByte(0x00);
1071 
1072 	file->Seek(lengthPos, SEEK_SET);
1073 	Write32Bit(byteCount);
1074 	file->Seek(0, SEEK_END);
1075 }
1076 
1077 //------------------------------------------------------------------------------
1078 
1079 void BMidiStore::WriteMetaEvent(BMidiEvent* event)
1080 {
1081 	// We only export the Tempo Change meta event.
1082 
1083 	if ((event->byte2 == 0x51) && (event->byte3 == 0x03))
1084 	{
1085 		uint32 val = 60000000 / event->tempo;
1086 
1087 		WriteByte(0xFF);
1088 		WriteByte(0x51);
1089 		WriteByte(0x03);
1090 		WriteByte(val >> 16);
1091 		WriteByte(val >> 8);
1092 		WriteByte(val);
1093 	}
1094 }
1095 
1096 
1097 //------------------------------------------------------------------------------
1098