Я пытаюсь понять, как работает следующая строка кода:
for (int i = 0; i < numSamples; i++) {
short ampValue = 0;
for (int byteNo = 0; byteNo < 2; byteNo++) {
ampValue |= (short) ((data[pointer++] & 0xFF) << (byteNo * 8));
}
amplitudes[i] = ampValue;
}
Насколько я понимаю, это чтение 2 байтов (как 2 байта на выборку) включенным образом, то есть ampValue состоит из двух байтовых чтений. Данные представляют собой фактический образец данных (файл), и указатель увеличивается, чтобы прочитать его до последнего образца. Но я не понимаю эту часть:
"data[pointer++] & 0xFF) << (byteNo * 8)); "
Кроме того, мне интересно, не имеет значения, хочу ли я читать это как двойное, а не короткое?
Похоже, данные [] - это массив байтов.
data [pointer++] дает вам значение байта в диапазоне [-128.. 127].
0xFF является int contstant, поэтому...
data [pointer++] & 0xFF повышает значение байта до значения int в диапазоне [-128.. 127]. Затем оператор & обнуляет все биты, которые не установлены в 0xFF (т.е. он обнуляет 24 верхних бита, оставляя только низкие 8 бит.
Значение этого выражения теперь будет находиться в диапазоне [0..255].
Оператор << сдвигает результат влево на биты (byteNo * 8). То же самое, что и сказать, умножает значение на 2, поднятое до мощности (byteNo * 8). Когда byteNo == 0, он умножается на 2 на мощность 0 (т.е. Умножается на 1). Когда byteNo == 1, он умножается на 2 на мощность 8 (т.е. Умножается на 256).
Этот цикл создает int в диапазоне [0..65535] (16 бит) из каждой пары байтов в массиве, беря первый член каждой пары в качестве младшего байта, а второй член - как высокий байт.
Это не сработает, чтобы объявить ampValue как double, потому что оператор \= не будет работать с двойным, но вы можете объявить массив амплитуд [] как массив из двух, а amplitudes[i] = ampValue
присваивания amplitudes[i] = ampValue
будут неявно повысить значение до двойного значения в диапазоне [0.0..65535.0].
Дополнительная информация: Не забывайте комментарий @KevinKrumwiede об ошибке в примере.
|=
даст тот же ответ, что и +=
. | Оператор, который работает только с int-подобными значениями, дает вам побитовый или . Таким образом, бит n будет установлен в результате, если бит n в любом из операндов установлен. В этом конкретном случае математика работает так, что не будет перекрытия между двумя значениями, которые объединены вместе, поэтому побитовое или эффективное действие равнозначно добавлению двух операндов.
В Java все байты подписаны. Выражение (data[pointer++] & 0xFF)
преобразует значение подписанного байта в int со значением байта, если оно было неподписанным. Тогда выражение << (byteNo * 8)
сдвигает левое результирующее значение на ноль или восемь бит в зависимости от значения byteNo
. Значение всего выражения назначается побитовым или ampValue
.
В этом коде есть ошибка. Значение ampValue
не сбрасывается до нуля между итерациями. И amplitude
не используется. Являются ли эти идентификаторы одинаковыми?
Позвольте сломать выражение:
|=
является побитовым и/или присваивающим оператором. a |= b
эквивалентно a = a | b
a = a | b
.(short)
выводит элемент int
из массива data
на short
.pointer++
- операция с pointer++
приращением. Значение pointer
будет возвращено и использовано, а затем сразу же будет увеличиваться каждый раз, когда он будет обращаться таким образом - это выгодно в этом случае, потому что внешний цикл циклически проходит через 2-байтовые выборки (через внутренний цикл) из смежных data
буфера, поэтому он продолжает увеличиваться.&
является побитовым оператором И, а 0xFF
является шестнадцатеричным значением для байта 0b11111111
(255 в десятичной 0b11111111
); data[pointer++] & 0xFF
выражения data[pointer++] & 0xFF
в основном говорят, для каждого бита в байте, извлеченном из массива data
, AND с 1
. В этом контексте он заставляет Java, который по умолчанию хранит подписанные байтовые объекты (т.е. значения от -128 до 127 в десятичном формате), чтобы вернуть значение в виде байта без знака (т.е. значения от 0 до 255 десятичных знаков).<<
. byteNo * 8
гарантирует, что вы только сдвигаете биты, когда это второй из двух байтов. После того, как два байта будут прочитаны, ampValue
теперь будет содержать значение образца как short
.