本文整理汇总了C++中MidiEvent::Type方法的典型用法代码示例。如果您正苦于以下问题:C++ MidiEvent::Type方法的具体用法?C++ MidiEvent::Type怎么用?C++ MidiEvent::Type使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类MidiEvent
的用法示例。
在下文中一共展示了MidiEvent::Type方法的6个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Build
MidiEvent MidiEvent::Build(const MidiEventSimple &simple) {
MidiEvent ev;
ev.m_delta_pulses = 0;
ev.m_status = simple.status;
ev.m_data1 = simple.byte1;
ev.m_data2 = simple.byte2;
if (ev.Type() == MidiEventType_Meta)
throw MidiError(MidiError_MetaEventOnInput);
return ev;
}
示例2: ReadFromStream
MidiEvent MidiEvent::ReadFromStream(istream &stream,
unsigned char last_status,
bool contains_delta_pulses) {
MidiEvent ev;
if (contains_delta_pulses)
ev.m_delta_pulses = parse_variable_length(stream);
else
ev.m_delta_pulses = 0;
// MIDI uses a compression mechanism called "running status".
// Anytime you read a status byte that doesn't have the highest-
// order bit set, what you actually read is the 1st data byte
// of a message with the status of the previous message.
ev.m_status = static_cast<unsigned char>(stream.peek());
if ((ev.m_status & 0x80) == 0)
ev.m_status = last_status;
else
// It was a status byte after all, just read past it
// in the stream
stream.read(reinterpret_cast<char*>(&ev.m_status), sizeof(unsigned char));
switch (ev.Type()) {
case MidiEventType_Meta:
ev.ReadMeta(stream);
break;
case MidiEventType_SysEx:
ev.ReadSysEx(stream);
break;
default:
ev.ReadStandard(stream);
break;
}
return ev;
}
示例3: Update
//.........这里部分代码省略.........
m_last_input_note_name = "";
delete m_state.midi_in;
m_state.midi_in = 0;
if (input_id >= 0) {
try {
m_state.midi_in = new MidiCommIn(input_id);
UserSetting::Set(InputDeviceKey, m_state.midi_in->GetDeviceDescription().name);
}
catch (MidiErrorCode) {
m_state.midi_in = 0;
}
}
else
UserSetting::Set(InputDeviceKey, InputKeySpecialDisabled);
}
if (m_state.midi_in && m_input_tile->IsPreviewOn()) {
// Read note events to display on screen
while (m_state.midi_in->KeepReading()) {
MidiEvent ev = m_state.midi_in->Read();
// send to output (for a possible audio preview)
if (m_state.midi_out)
m_state.midi_out->Write(ev);
if (ev.Type() == MidiEventType_NoteOff || ev.Type() == MidiEventType_NoteOn) {
string note = MidiEvent::NoteName(ev.NoteNumber());
if (ev.Type() == MidiEventType_NoteOn && ev.NoteVelocity() > 0)
m_last_input_note_name = note;
else
if (note == m_last_input_note_name)
m_last_input_note_name = "";
}
}
}
else
m_last_input_note_name = "";
if (IsKeyPressed(KeyEscape) || m_back_button.hit) {
delete m_state.midi_out;
m_state.midi_out = 0;
delete m_state.midi_in;
m_state.midi_in = 0;
delete m_state.midi;
m_state.midi = 0;
Compatible::GracefulShutdown();
return;
}
if (IsKeyPressed(KeyEnter) || m_continue_button.hit) {
示例4: BuildTempoTrack
// NOTE: This is required for much of the other functionality provided
// by this class, however, this causes a destructive change in the way
// the MIDI is represented internally which means we can never save the
// file back out to disk exactly as we loaded it.
//
// This adds an extra track dedicated to tempo change events. Tempo events
// are extracted from every other track and placed in the new one.
//
// This allows quick(er) calculation of wall-clock event times
void Midi::BuildTempoTrack()
{
// This map will help us get rid of duplicate events if
// the tempo is specified in every track (as is common).
//
// It also does sorting for us so we can just copy the
// events right over to the new track.
std::map<unsigned long, MidiEvent> tempo_events;
// Run through each track looking for tempo events
for (MidiTrackList::iterator t = m_tracks.begin(); t != m_tracks.end(); ++t)
{
for (size_t i = 0; i < t->Events().size(); ++i)
{
MidiEvent ev = t->Events()[i];
unsigned long ev_pulses = t->EventPulses()[i];
if (ev.Type() == MidiEventType_Meta && ev.MetaType() == MidiMetaEvent_TempoChange)
{
// Pull tempo event out of both lists
//
// Vector is kind of a hassle this way -- we have to
// walk an iterator to that point in the list because
// erase MUST take an iterator... but erasing from a
// list invalidates iterators. bleah.
MidiEventList::iterator event_to_erase = t->Events().begin();
MidiEventPulsesList::iterator event_pulse_to_erase = t->EventPulses().begin();
for (size_t j = 0; j < i; ++j) { ++event_to_erase; ++event_pulse_to_erase; }
t->Events().erase(event_to_erase);
t->EventPulses().erase(event_pulse_to_erase);
// Adjust next event's delta time
if (t->Events().size() > i)
{
// (We just erased the element at i, so
// now i is pointing to the next element)
unsigned long next_dt = t->Events()[i].GetDeltaPulses();
t->Events()[i].SetDeltaPulses(ev.GetDeltaPulses() + next_dt);
}
// We have to roll i back for the next loop around
--i;
// Insert our newly stolen event into the auto-sorting map
tempo_events[ev_pulses] = ev;
}
}
}
// Create a new track (always the last track in the track list)
m_tracks.push_back(MidiTrack::CreateBlankTrack());
MidiEventList &tempo_track_events = m_tracks[m_tracks.size()-1].Events();
MidiEventPulsesList &tempo_track_event_pulses = m_tracks[m_tracks.size()-1].EventPulses();
// Copy over all our tempo events
unsigned long previous_absolute_pulses = 0;
for (std::map<unsigned long, MidiEvent>::const_iterator i = tempo_events.begin(); i != tempo_events.end(); ++i)
{
unsigned long absolute_pulses = i->first;
MidiEvent ev = i->second;
// Reset each of their delta times while we go
ev.SetDeltaPulses(absolute_pulses - previous_absolute_pulses);
previous_absolute_pulses = absolute_pulses;
// Add them to the track
tempo_track_event_pulses.push_back(absolute_pulses);
tempo_track_events.push_back(ev);
}
}
示例5: Write
void MidiCommOut::Write(const MidiEvent &out)
{
MidiEventSimple simple;
if (!out.GetSimpleEvent(&simple)) return;
if (m_description.id == 0)
{
MusicDeviceMIDIEvent(m_device, simple.status, simple.byte1, simple.byte2, 0);
if (out.Type() == MidiEventType_Controller)
{
// If we just set the data byte for some previous controller event,
// "close off" changes to it. That way, if the output device doesn't
// accept this (N)RPN event, it won't accidentally overwrite the last
// one that it did.
// NOTE: Hopefully there aren't any (N)RPN types that rely on sequentially
// changing these values smoothly. That seems like a pretty special
// case though. I'll cross that bridge when I come to it.
//
// I tried "closing" controller changes just *before* a data (N)RPN
// event (in order to cut off some hypothetical previous (N)RPN event
// at the last possible second), but it didn't appear to work.
// NOTE: This appears to only be necessary for the DLS Synth. I suppose
// I've only got a VERY limited pool of MIDI devices to work with though,
// and I'm sure there are a handful of devices out there that have the
// same problem. Again, I'll cross that bridge when I come to it.
// Detect coarse data byte changes
if (simple.byte1 == 0x06)
{
MusicDeviceMIDIEvent(m_device, simple.status, 0x64, 0x7F, 0); // RPN (coarse) reset
MusicDeviceMIDIEvent(m_device, simple.status, 0x62, 0x7F, 0); // NRPN (coarse) reset
}
// Detect fine data byte changes
if (simple.byte1 == 0x26)
{
MusicDeviceMIDIEvent(m_device, simple.status, 0x65, 0x7F, 0); // RPN (fine) reset
MusicDeviceMIDIEvent(m_device, simple.status, 0x63, 0x7F, 0); // NRPN (fine) reset
}
}
}
else
{
const static int PacketBufferSize = 128;
Byte packet_buffer[PacketBufferSize];
MIDIPacketList *packets = reinterpret_cast<MIDIPacketList*>(packet_buffer);
MIDIPacket *packet = MIDIPacketListInit(packets);
int messageSize = 3;
if (out.Type() == MidiEventType_ProgramChange || out.Type() == MidiEventType_ChannelPressure) messageSize = 2;
const static int MaxMessageSize = 3;
const Byte message[MaxMessageSize] = { simple.status, simple.byte1, simple.byte2 };
packet = MIDIPacketListAdd(packets, PacketBufferSize, packet, 0, messageSize, message);
MIDISend(m_port, m_endpoint, packets);
}
}
示例6: Listen
void PlayingState::Listen() {
if (!m_state.midi_in)
return;
while (m_state.midi_in->KeepReading()) {
microseconds_t cur_time = m_state.midi->GetSongPositionInMicroseconds();
MidiEvent ev = m_state.midi_in->Read();
if (m_state.midi_in->ShouldReconnect())
{
m_state.midi_in->Reconnect();
m_state.midi_out->Reconnect();
continue;
}
// Just eat input if we're paused
if (m_paused)
continue;
// We're only interested in NoteOn and NoteOff
if (ev.Type() != MidiEventType_NoteOn && ev.Type() != MidiEventType_NoteOff)
continue;
// Octave Sliding
ev.ShiftNote(m_note_offset);
int note_number = ev.NoteNumber();
string note_name = MidiEvent::NoteName(note_number);
// On key release we have to look for existing "active" notes and turn them off.
if (ev.Type() == MidiEventType_NoteOff || ev.NoteVelocity() == 0) {
// NOTE: This assumes mono-channel input. If they're piping an entire MIDI file
// (or even the *same* MIDI file) through another source, we could get the
// same NoteId on different channels -- and this code would start behaving
// incorrectly.
for (ActiveNoteSet::iterator i = m_active_notes.begin(); i != m_active_notes.end(); ++i) {
if (ev.NoteNumber() != i->note_id)
continue;
// Play it on the correct channel to turn the note we started
// previously, off.
ev.SetChannel(i->channel);
if (m_state.midi_out)
m_state.midi_out->Write(ev);
m_active_notes.erase(i);
break;
}
// User releases the key
// If we delete this line, than all pressed keys will be gray until
// it is unpressed automatically
m_keyboard->SetKeyActive(note_name, false, Track::FlatGray);
userPressedKey(note_number, false);
continue;
}
TranslatedNoteSet::iterator closest_match = m_notes.end();
for (TranslatedNoteSet::iterator i = m_notes.begin(); i != m_notes.end(); ++i) {
const microseconds_t window_start = i->start - (KeyboardDisplay::NoteWindowLength / 2);
const microseconds_t window_end = i->start + (KeyboardDisplay::NoteWindowLength / 2);
// As soon as we start processing notes that couldn't possibly
// have been played yet, we're done.
if (window_start > cur_time)
break;
if (i->state != UserPlayable)
continue;
if (window_end > cur_time && i->note_id == ev.NoteNumber()) {
if (closest_match == m_notes.end()) {
closest_match = i;
continue;
}
microseconds_t this_distance = cur_time - i->start;
if (i->start > cur_time)
this_distance = i->start - cur_time;
microseconds_t known_best = cur_time - closest_match->start;
if (closest_match->start > cur_time)
known_best = closest_match->start - cur_time;
if (this_distance < known_best)
closest_match = i;
}
}
Track::TrackColor note_color = Track::FlatGray;
if (closest_match != m_notes.end()) {
note_color = m_state.track_properties[closest_match->track_id].color;
// "Open" this note so we can catch the close later and turn off
// the note.
//.........这里部分代码省略.........