123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- #include <vector>
- #include <iostream>
- #include "Message.h"
- namespace midi {
- Message* Message::parse(std::vector<unsigned char> &messageBytes)
- {
- // msg[0] has 8 bits
- // - 4 higher significant bits: message type
- // - 4 lower significant bits: channel (0 - 15)
- unsigned char messageType = messageBytes[0] >> 4;
- if(messageType == 0xF)
- {
- // system message
- throw "Message::parseMessage() does not support system messages yet.";
- }
- else
- {
- // channel message
- ChannelMessage::Channel channel = messageBytes[0] & 0xF;
- switch(messageType)
- {
- case NoteOnMessage::messageType:
- case NoteOffMessage::messageType:
- {
- unsigned char pitch = messageBytes[1];
- unsigned char velocity = messageBytes[2];
- if(messageType == NoteOffMessage::messageType || velocity == 0)
- {
- return new NoteOffMessage(channel, pitch, velocity);
- }
- else
- {
- return new NoteOnMessage(channel, pitch, velocity);
- }
- }
- case ControlChangeMessage::messageType:
- return new ControlChangeMessage(channel, messageBytes[1], messageBytes[2]);
- case ProgramChangeMessage::messageType:
- return new ProgramChangeMessage(channel, messageBytes[1]);
- case PitchBendChangeMessage::messageType:
- // messageBytes[1] are the least significant 7 bits.
- // messageBytes[2] are the most significant 7 bits.
- return new PitchBendChangeMessage(
- channel,
- (messageBytes[2] << 7) + messageBytes[1]
- );
- default:
- throw "Message::parseMessage() does not support the given type of channel message yet.";
- }
- }
- }
- bool Message::operator==(const Message& message) const
- {
- return getBytes() == message.getBytes();
- }
- std::vector<unsigned char> NoteOnMessage::getBytes() const
- {
- std::vector<unsigned char> bytes(3);
- bytes[0] = messageType << 4 | channel;
- bytes[1] = pitch;
- bytes[2] = velocity;
- return bytes;
- }
- std::vector<unsigned char> NoteOffMessage::getBytes() const
- {
- std::vector<unsigned char> bytes(3);
- bytes[0] = messageType << 4 | channel;
- bytes[1] = pitch;
- bytes[2] = velocity;
- return bytes;
- }
- std::vector<unsigned char> ControlChangeMessage::getBytes() const
- {
- std::vector<unsigned char> bytes(3);
- bytes[0] = messageType << 4 | channel;
- bytes[1] = control;
- bytes[2] = value;
- return bytes;
- }
- std::vector<unsigned char> ProgramChangeMessage::getBytes() const
- {
- std::vector<unsigned char> bytes(2);
- bytes[0] = messageType << 4 | channel;
- bytes[1] = program;
- return bytes;
- }
- std::vector<unsigned char> PitchBendChangeMessage::getBytes() const
- {
- std::vector<unsigned char> bytes(3);
- bytes[0] = messageType << 4 | channel;
- // bytes[1] are the seven least significant bits.
- // bytes[2] are the seven most significant bits.
- bytes[1] = value & ((1 << 7) - 1);
- bytes[2] = value >> 7;
- return bytes;
- }
- std::ostream& operator<<(std::ostream& stream, const Message& message)
- {
- message.print(stream);
- return stream;
- }
- void NoteOnMessage::print(std::ostream& stream) const
- {
- stream << "channel #" << (unsigned short)(channel + 1) << ": "
- << "note " << (unsigned short)pitch << " with velocity " << (unsigned short)velocity << " on\n";
- }
- void NoteOffMessage::print(std::ostream& stream) const
- {
- stream << "channel #" << (unsigned short)(channel + 1) << ": "
- << "note " << (unsigned short)pitch << " off\n";
- }
- void ControlChangeMessage::print(std::ostream& stream) const
- {
- stream << "channel #" << (unsigned short)(channel + 1) << ": "
- << "change value of control #" << (unsigned short)(control + 1)
- << " to " << (unsigned short)value << "\n";
- }
- void ProgramChangeMessage::print(std::ostream& stream) const
- {
- stream << "channel #" << (unsigned short)(channel + 1) << ": "
- << "switch to program # " << (unsigned short)(program + 1) << "\n";
- }
- void PitchBendChangeMessage::print(std::ostream& stream) const
- {
- stream << "channel #" << (unsigned short)(channel + 1) << ": "
- << "pitch bended to " << value << "\n";
- }
- } // namespace
|