| 1360 | } |
| 1361 | |
| 1362 | VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit) { |
| 1363 | auto bitsCount = static_cast<int>(encoded5bit.size() * 8); |
| 1364 | auto valuesCount = bitsCount / 5; |
| 1365 | if (!valuesCount) { |
| 1366 | return VoiceWaveform(); |
| 1367 | } |
| 1368 | |
| 1369 | // Read each 5 bit of encoded5bit as 0-31 unsigned char. |
| 1370 | // We count the index of the byte in which the desired 5-bit sequence starts. |
| 1371 | // And then we read a uint16 starting from that byte to guarantee to get all of those 5 bits. |
| 1372 | // |
| 1373 | // BUT! if it is the last byte we have, we're not allowed to read a uint16 starting with it. |
| 1374 | // Because it will be an overflow (we'll access one byte after the available memory). |
| 1375 | // We see, that only the last 5 bits could start in the last available byte and be problematic. |
| 1376 | // So we read in a general way all the entries in a general way except the last one. |
| 1377 | auto result = VoiceWaveform(valuesCount, 0); |
| 1378 | auto bitsData = encoded5bit.constData(); |
| 1379 | for (auto i = 0, l = valuesCount - 1; i != l; ++i) { |
| 1380 | auto byteIndex = (i * 5) / 8; |
| 1381 | auto bitShift = (i * 5) % 8; |
| 1382 | auto value = *reinterpret_cast<const uint16*>(bitsData + byteIndex); |
| 1383 | result[i] = static_cast<char>((value >> bitShift) & 0x1F); |
| 1384 | } |
| 1385 | auto lastByteIndex = ((valuesCount - 1) * 5) / 8; |
| 1386 | auto lastBitShift = ((valuesCount - 1) * 5) % 8; |
| 1387 | auto lastValue = (lastByteIndex == encoded5bit.size() - 1) |
| 1388 | ? static_cast<uint16>(*reinterpret_cast<const uchar*>(bitsData + lastByteIndex)) |
| 1389 | : *reinterpret_cast<const uint16*>(bitsData + lastByteIndex); |
| 1390 | result[valuesCount - 1] = static_cast<char>((lastValue >> lastBitShift) & 0x1F); |
| 1391 | |
| 1392 | return result; |
| 1393 | } |
| 1394 | |
| 1395 | QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform) { |
| 1396 | auto bitsCount = waveform.size() * 5; |