Ниже приведен код, который я использовал для чтения 16-битных и 32-битных образцов, которые работают просто отлично.
У меня вопрос, как я могу прочитать оставшиеся 8-битные без знака, 24-битные со знаком и 32-битные поплавок WAVs?
Прочитайте один пример 16-битного подписанного wav:
short buffer;
file.read( ( char * ) &readbuffer, 2 );
Прочитайте один пример 32-битного подписанного wav:
int buffer;
file.read( ( char * ) &readbuffer, 4 );
Вы делаете несколько предположений о целевой машине. По данным Microsoft Формат WAV, Все образцы данных имеют порядок байтов. Вы также ожидаете, что различные типы данных будут иметь желаемый размер, что может не всегда иметь место.
Но так как ваши текущие процедуры работают на вас, мы пока не будем на этом фокусироваться (но вам, вероятно, следует исправить это в какой-то момент)
Если мы забудем о страшном порядке байтов и нестандартных размерах, 32-битный случай с плавающей запятой становится относительно простым, если использовать другой код в качестве шаблона:
float buffer;
file.read( ( char * ) &buffer, 4 );
Этот вопрос более подробно описывает чтение плавающих объектов из двоичного источника.
Так как мы знаем, что ваша машина правильно интерпретирует 16- и 32-битные случаи, мы можем предположить, что это little-endian. Это означает, что вы можете просто прочитать все в unsigned int, которое было инициализировано нулем, а остальные байты уже правильно заполнены для вас:
unsigned int buffer = 0;
file.read( ( char * ) &buffer, 1 ); // 8bit unsigned integer
buffer = 0;
file.read( ( char * ) &buffer, 3 ); // 24bit unsigned integer
Наконец, если вы читаете целое число со знаком, вам нужно заполнить оставшиеся байты буферной переменной в зависимости от значения только что прочитанного числа:
Этот код работает с 24-битным целым числом со знаком:
long buffer;
int number_of_bytes = 3; // 24 bit signed integer
file.read( (char *) &buffer, number_of_bytes);
// Determine the padding byte
unsigned char padding_byte = 0;
if ( ((char*) &buffer)[number_of_bytes - 1] & 128) {
padding_byte = 255;
}
// Pad the data
for (int i = number_of_bytes; i < sizeof(buffer); i++) {
((char*) &buffer)[i] = padding_byte;
}
Опять же, я чувствую, что должен указать, что этот код не будет работать на некоторых машинах, потому что вы не проверяете порядок байтов. Но все, что вам нужно сделать, чтобы это исправить, это проверить порядок байтов машины, на которой выполняется код и обратный порядок байтов, если вы находитесь на машине с прямым порядком байтов.
Других решений пока нет …