Разделите части шестнадцатеричного значения uint32_t на более мелкие части в переполнении стека

У меня есть uint32_t следующим образом:

uint32_t midiData=0x9FCC00;

Мне нужно разделить этот uint32_t на более мелкие части, так что 9 становится его собственной сущностью, F становится его собственной сущностью, а CC становится его собственной сущностью. Если вам интересно, что я делаю, я пытаюсь разбить части MIDI-сообщения, чтобы ими было легче управлять в моей программе.

я нашел это решение, но проблема в том, что я не знаю, как применить его к разделу CC, и что я не уверен, что этот метод работает с C ++.

Вот что у меня так далеко:

uint32_t midiData=0x9FCC00;

uint32_t status = 0x0FFFFF & midiData; // Retrieve 9
uint32_t channel = (0xF0FFFF & midiData)>>4; //Retrieve F
uint32_t note = (0xFF00FF & midiData) >> 8; //Retrieve CC

Это правильно для C ++? Причина, по которой я спрашиваю, заключается в том, что я никогда раньше не использовал C ++ и его синтаксис использования> и < всегда смущал меня (поэтому я стараюсь этого избегать).

-1

Решение

Вы можете использовать оператор сдвига бит >> и оператор битовой маскировки & в C ++ также.
Есть, однако, некоторые вопросы о том, как вы его используете:

оператор v1 & v2 дает число, построенное из тех битов, которые установлены в обоих v1 а также v2такой, что, например, 0x12 & 0xF0 дает 0x10не 0x02, Кроме того, оператор сдвига бит принимает количество битов, а одна цифра в шестнадцатеричном числе (которое обычно называется полубайтом) состоит из 4 битов (0x0..0xF требует 4 бита). Итак, если у вас есть 0x12 и хочу получить 0x01, ты должен написать 0x12 >>4,
Следовательно, ваши смены тоже должны быть адаптированы:

#define BITS_OF_A_NIBBLE 4

unsigned char status = (midiData & 0x00F00000) >> (5*BITS_OF_A_NIBBLE);
unsigned char channel = (midiData & 0x000F0000) >> (4*BITS_OF_A_NIBBLE);
unsigned char note = (midiData & 0x0000FF00) >> (2*BITS_OF_A_NIBBLE);
unsigned char theRest = (midiData & 0x000000FF);
1

Другие решения

Вы имеете это задом наперед, в некотором смысле.

В булевой логике & является побитовым-И), И что-то с 0 исключит это. Знаю это F в шестнадцатеричном виде 1111 в двоичном виде строка 0x9FCC00 & 0x0FFFFF даст вам все шестнадцатеричные цифры, кроме 9, в противоположность тому, что вы хотите.

Итак, для статуса:

uint32_t status = 0xF000000 & midiData; // Retrieve 9

На самом деле, это даст вам 0x900000. Если вы хотите 0x9 (также 9 в десятичном виде), вам нужно сдвинуть результат в битах.

Теперь, правильный оператор сдвига битов (скажем, X >> 4) означает перемещение X 4 бит вправо; деление на 16. Это 4 бита, а не 4 шестнадцатеричных числа. 1 шестнадцатеричная цифра == 4 бита, поэтому для получения 9 из 0x900000 необходимо 0x900000 >> 20,

Итак, чтобы собрать их вместе, чтобы получить статус 9:

uint32_t status = (0xF000000 & midiData) >> 20;

Подобный процесс даст вам остальные значения, которые вы хотите.

0

В общем, я бы рекомендовал сначала сместить, а затем замаскировать — это менее подвержено ошибкам:

uint8_t cmd = (midiData >> 16) & 0xff;
uint8_t note = (midiData >> 8) & 0x7f;     // MSB can't be set
uint8_t velocity = (midiData >> 0) & 0x7f; // ditto

а затем разделить cmd переменная:

uint8_t status = (cmd & 0xf0);             // range 0x00 .. 0xf0
uint8_t channel = (cmd & 0x0f);            // range 0 .. 15

Я лично не стал бы картировать status значение обратно в диапазоне 0 .. 15 — обычно считается, что, например, 0x90 это «примечание», а не просто значение 9,

0
По вопросам рекламы [email protected]