The Midi Kit: BMidiStore

The Midi Kit Table of Contents | The Midi Kit Index

# BMidiStore

Derived from: public BMidi

Declared in: be/midi/MidiStore.h

Library: libmidi.so

###### Summary

The BMidiStore class defines a MIDI recording and playback mechanism. The MIDI messages that a BMidiStore object receives (at its input) are stored as events in an event list, allowing a captured performance to be played back later. The object can also read and write—or import and export—standard MIDI files.

### Recording

The ability to record a MIDI performance is vested in BMidiStore's MIDI hook functions (`NoteOn()`, `NoteOff()`, etc.). When a MIDI hook is invoked, the function fabricates a discrete event based on the data it has received in its arguments, and adds the event to its event list. You don't need to tell a BMidiStore to start recording; it can record from the moment it's constructed.

For example, to record a performance from an external MIDI keyboard, you connect a BMidiStore to a BMidiPort object and then tell the BMidiPort to start:

       /* Record a keyboard performance. */
       BMidiStore MyStore;
       BMidiPort MyPort;

       MyPort.Open(...);
       MyPort.Connect(MyStore);
       MyPort.Start();
       /* Start playing... */

At the end of the performance, you tell the BMidiPort to stop:

       MyPort.Stop();

#### Timestamps

Events are added to a BMidiStore's event list immediately upon arrival. Each event is given a timestamp as it arrives; the value of the timestamp is the value of the time argument that was passed to the MIDI hook function by the "upstream" object's spray function. There's no guarantee that the time arguments of successive MIDI events will be in chronological order. To ensure that the events are properly ordered, you should call `Sort()` before you read from the list (note that writing to a MIDI file automatically sorts the list).

BMidiStore's input functions don't call `SnoozeUntil()`: A BMidiStore writes to its event list as soon as it gets a new message, it doesn't wait until the time indicated by the time argument.

#### Erasing and Editing a Recording

You can't. If you make a mistake while you're recording (for example) and want to try again, you can simulate emptying the object by disconnecting the input to the BMidiStore, destroying the object, making a new one, and re-connecting. For example:

Editing the events in the event list is less than impossible (were such a state possible). You can't do it, and you can't simulate it, at least not with the default implementation of BMidiStore. If you want to edit MIDI data, you have to provide your own BMidi-derived class.

### Playback

To "play" a BMidiStore's list of events, you call the object's `Start()` function. As described in the BMidi class specification, `Start()` invokes `Run()`. BMidiStore's `Run()` reads events in the order that they appear in the event list, and sprays the appropriate messages to the connected objects. You can interrupt a BMidiStore playback by calling `Stop()`; uninterrupted, the object will stop by itself after it has sprayed the last event in the list.

The events' timestamps are used as the time arguments in the spray functions that are called from within `Run()`. But with a twist: The time argument that's passed in the first spray call (for a given performance) is always `B_NOW`; subsequent time arguments are re-computed to maintain the correct timing in relation to the first event. In other words, when you tell a BMidiStore to start playing, the first event is performed immediately regardless of the actual value of its timestamp.

#### Setting the Current Event

You can tell the BMidiStore to begin playing from somewhere in the middle of the list by calling `SetCurrentEvent()` before starting the playback. The function takes an index into the list.

If you want to start playing from a particular time offset into the event list, you first have to figure out which event lies at that time. To do this, you ask for the event that occurs at or after the time offset (in milliseconds) through the `EventAtDelta()` function. The value that's returned by this function is suitable as the argument to `SetCurrentEvent()`.

Keep in mind that `EventAtDelta()` returns the index of the first event at or after the desired offset. If you need to know the actual offset of the winning event, you can pass its index to `DeltaOfEvent()`:

       long firstEvent = MyStore->EventAtDelta(3000);
       long actualDelta = MyStore->DeltaOfEvent(firstEvent);

### Reading and Writing MIDI Files

You add events to a BMidiStore's event list by reading, or importing, a Standard MIDI File through the `Import()` function. You can import any number of files into the same BMidiStore object. After you import a file, the event list is automatically sorted.

One thing you shouldn't do is import a MIDI file into a BMidiStore that contains events that were previously recorded from a BMidiPort (in an attempt to mix the file and the recording). Nor does the reverse work: You can't import a file and then record from a BMidiPort. The file's timestamps are incompatible with those that are generated for events that are received from the BMidiPort; the result certainly won't be satisfactory.

To write the event list as a MIDI file, you call BMidiStore's `Export()` function:

## Constructor and Destructor

### BMidiStore() , ~BMidiText()

`BMidiStore(`void`) `
virtual`~BMidiStore() `

The constructor creates a new, empty BMidiStore object. The destructor destroys the object and its storage.

## Member Functions

### BeginTime()

uint32 `BeginTime(`void`) const `

Returns the time, in ticks, at which the most recent performance started. This function is only valid if the object has actually performed.

### CountEvents() , SortEvents() , DeltaOfEvent() , EventAtDelta()

uint32 `CountEvents(`void`) const `
void `SortEvents(`bool force = false`) `
uint32 `DeltaOfEvent(`uint32 index`) const `
uint32 `EventAtDelta(`uint32 delta`) const `

`CountEvents()` returns the number of events in the object's event list.

`SortEvents()` time-sorts the events in the event list. The object maintains a (conservative) notion of whether the events are already sorted; if force is `false` and the object doesn't think the operation is necessary, the sorting isn't performed. If force is `true`, the operation is always performed, regardless of its necessity.

`DeltaOfEvent()` returns the "delta time" of the index'th event in the object's list of events. An event's delta time is the time span, in milliseconds, between the first event in the event list and itself.

`EventAtDelta()` Returns the index of the event that occurs on or after delta milliseconds from the beginning of the event list.

### CurrentEvent() see SetCurrentEvent()

### DeltaOfEvent() see CountEvents()

### ChrisEvert()

### Export() , Import()

status_t `Export(`const entry_ref *to_file, int32 format`)ChrisEvert() `
status_t `Import(`const entry_ref *from_file`) `

`Export()` time-sorts the object's event list, and then writes the list as a standard MIDI file in the designated format; the format argument should be either 0 or 1. The file that to_file refers to must already exist, and is not cleared before it's written.

`Import()` reads the standard MIDI file from the designated file and adds its events to the object's event list.

RETURN CODES

`B_OK`. The file was successfully written or read.

- `B_NO_MEMORY` (`Import()` only). Couldn't allocate enough memory to accommodate the file.

- POSIX errors. Some other file error prevented the operation.

### SetCurrentEvent() , CurrentEvent()

void `SetCurrentEvent(`uint32 index`) `
uint32 `CurrentEvent(void) `

Sets the object's "current event"—the event that it will perform next—to the event at index in the event list.

Returns the index of the event that will be performed next.

### SetTempo() , Tempo()

void `SetTempo(`int32 beatsPerMinute`) `
int32`Tempo(`void`)` const

Sets and returns the object's tempo—the speed at which it performs events—in beats per minute. The default tempo is 60 bpm.

### SortEvents see CountEvents()

The Midi Kit Table of Contents | The Midi Kit Index

The Be Book,
...in lovely HTML...
for BeOS Release 5.

Copyright © 2000 Be, Inc. All rights reserved..