| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * mpq-wave.c -- WAVE decompression helpers for MPQ audio payloads. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2003-2026 Maik Broemme <mbroemme@libmpq.org> | ||
| 5 | * | ||
| 6 | * This source was adapted from the C++ version of wave.cpp included | ||
| 7 | * in stormlib. The C++ version belongs to the following authors: | ||
| 8 | * | ||
| 9 | * Ladislav Zezula <ladik@zezula.net> | ||
| 10 | * Tom Amigo <tomamigo@apexmail.com> | ||
| 11 | * | ||
| 12 | * This file is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU Lesser General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2.1 of the License, or | ||
| 15 | * (at your option) any later version. | ||
| 16 | * | ||
| 17 | * This file is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU Lesser General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU Lesser General Public License | ||
| 23 | * along with this file; if not, see <https://www.gnu.org/licenses/>. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include "mpq-wave.h" | ||
| 27 | #include "mpq-endian.h" | ||
| 28 | #include "mpq-internal.h" | ||
| 29 | #include <libmpq/mpq.h> | ||
| 30 | #include <stdlib.h> | ||
| 31 | #include <string.h> | ||
| 32 | |||
| 33 | /* Predictor-index adjustments used by the MPQ ADPCM WAVE decoder. */ | ||
| 34 | static const uint32_t wave_step_adjustments[] = { | ||
| 35 | 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006, | ||
| 36 | 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, | ||
| 37 | 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, | ||
| 38 | 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008 | ||
| 39 | }; | ||
| 40 | |||
| 41 | /* Step-size table used by the MPQ ADPCM WAVE decoder. */ | ||
| 42 | static const uint32_t wave_step_sizes[] = { | ||
| 43 | 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, | ||
| 44 | 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F, | ||
| 45 | 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042, | ||
| 46 | 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F, | ||
| 47 | 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133, | ||
| 48 | 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292, | ||
| 49 | 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583, | ||
| 50 | 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0, | ||
| 51 | 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954, | ||
| 52 | 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B, | ||
| 53 | 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462, | ||
| 54 | 0x00007FFF | ||
| 55 | }; | ||
| 56 | |||
| 57 | /* Quantize one PCM predictor difference into the MPQ ADPCM control byte. | ||
| 58 | * The predictor and step index are updated in place so the next sample uses | ||
| 59 | * the same adaptive state as the matching decoder. */ | ||
| 60 | static uint8_t | ||
| 61 | 6507 | wave_encode_delta(int32_t difference, int32_t *predictor, int32_t *step_index, uint32_t shift) | |
| 62 | { | ||
| 63 | 6507 | uint32_t step = wave_step_sizes[*step_index]; | |
| 64 | 6507 | uint32_t magnitude = (difference < 0) ? (uint32_t)-difference : (uint32_t)difference; | |
| 65 | 6507 | uint32_t code = difference < 0 ? 0x40u : 0; | |
| 66 | uint32_t bit; | ||
| 67 | 6507 | int32_t delta = (int32_t)(step >> shift); | |
| 68 |
2/2✓ Branch 0 taken 39042 times.
✓ Branch 1 taken 6507 times.
|
45549 | for (bit = 0; bit < 6; bit++) { |
| 69 | 39042 | uint32_t contribution = step >> bit; | |
| 70 |
2/2✓ Branch 0 taken 15782 times.
✓ Branch 1 taken 23260 times.
|
39042 | if (magnitude >= (uint32_t)(delta + (int32_t)contribution)) { |
| 71 | 15782 | code |= 1u << bit; | |
| 72 | 15782 | delta += (int32_t)contribution; | |
| 73 | } | ||
| 74 | } | ||
| 75 |
2/2✓ Branch 0 taken 3253 times.
✓ Branch 1 taken 3254 times.
|
6507 | if (difference < 0) |
| 76 | 3253 | *predictor -= delta; | |
| 77 | else | ||
| 78 | 3254 | *predictor += delta; | |
| 79 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6507 times.
|
6507 | if (*predictor > 32767) |
| 80 | ✗ | *predictor = 32767; | |
| 81 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6507 times.
|
6507 | if (*predictor < -32768) |
| 82 | ✗ | *predictor = -32768; | |
| 83 | 6507 | *step_index += (int32_t)wave_step_adjustments[code & 0x1f]; | |
| 84 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6507 times.
|
6507 | if (*step_index < 0) |
| 85 | ✗ | *step_index = 0; | |
| 86 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6507 times.
|
6507 | if (*step_index > 0x58) |
| 87 | ✗ | *step_index = 0x58; | |
| 88 | 6507 | return (uint8_t)code; | |
| 89 | } | ||
| 90 | |||
| 91 | /* Inspect a RIFF/WAVE prefix and validate its PCM16 channel configuration. | ||
| 92 | * Chunk boundaries, padding, channel count, sample width, and complete PCM | ||
| 93 | * frames are checked before offsets and sizes are returned to the caller. */ | ||
| 94 | int32_t | ||
| 95 | ✗ | libmpq__wave_probe_pcm16(const uint8_t *data, uint32_t size, libmpq_wave_info_s *info) | |
| 96 | { | ||
| 97 | ✗ | uint32_t pos = 12; | |
| 98 | uint32_t end; | ||
| 99 | ✗ | uint16_t channels = 0; | |
| 100 | ✗ | uint16_t format = 0; | |
| 101 | ✗ | uint16_t bits = 0; | |
| 102 | ✗ | uint32_t data_offset = 0; | |
| 103 | ✗ | uint32_t data_size = 0; | |
| 104 | ✗ | if (data == NULL || info == NULL || size < 12 || memcmp(data, "RIFF", 4) != 0 || | |
| 105 | ✗ | memcmp(data + 8, "WAVE", 4) != 0) | |
| 106 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 107 | ✗ | end = size; | |
| 108 | |||
| 109 | /* Walk RIFF chunks while honoring the required even-byte chunk padding. */ | ||
| 110 | ✗ | while (pos + 8 <= end) { | |
| 111 | ✗ | uint32_t chunk_size = libmpq__load_le32(data + pos + 4); | |
| 112 | ✗ | uint32_t next = pos + 8 + chunk_size + (chunk_size & 1u); | |
| 113 | ✗ | if (next < pos || next > end) | |
| 114 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 115 | ✗ | if (memcmp(data + pos, "fmt ", 4) == 0 && chunk_size >= 16) { | |
| 116 | ✗ | format = libmpq__load_le16(data + pos + 8); | |
| 117 | ✗ | channels = libmpq__load_le16(data + pos + 10); | |
| 118 | ✗ | bits = libmpq__load_le16(data + pos + 22); | |
| 119 | ✗ | } else if (memcmp(data + pos, "data", 4) == 0) { | |
| 120 | ✗ | data_offset = pos + 8; | |
| 121 | ✗ | data_size = chunk_size; | |
| 122 | } | ||
| 123 | ✗ | pos = next; | |
| 124 | } | ||
| 125 | ✗ | if (format != 1 || (channels != 1 && channels != 2) || bits != 16 || data_offset == 0 || | |
| 126 | ✗ | data_offset > size || (data_size % (channels * 2)) != 0) | |
| 127 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 128 | ✗ | info->channels = channels; | |
| 129 | ✗ | info->data_offset = data_offset; | |
| 130 | ✗ | info->data_size = data_size; | |
| 131 | ✗ | return LIBMPQ_SUCCESS; | |
| 132 | } | ||
| 133 | |||
| 134 | /* Validate a RIFF/WAVE prefix when later PCM bytes are not buffered yet. | ||
| 135 | * The available prefix must contain the format and data chunk headers, while | ||
| 136 | * the declared data range must fit within the complete writer file size. */ | ||
| 137 | int32_t | ||
| 138 | 2 | libmpq__wave_probe_pcm16_prefix( | |
| 139 | const uint8_t *data, uint32_t prefix_size, uint64_t file_size, libmpq_wave_info_s *info | ||
| 140 | ) | ||
| 141 | { | ||
| 142 | 2 | uint32_t pos = 12; | |
| 143 | 2 | uint16_t channels = 0; | |
| 144 | 2 | uint16_t format = 0; | |
| 145 | 2 | uint16_t bits = 0; | |
| 146 | 2 | uint32_t data_offset = 0; | |
| 147 | 2 | uint32_t data_size = 0; | |
| 148 | |||
| 149 |
4/8✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2 | if (data == NULL || info == NULL || prefix_size < 12 || file_size < prefix_size || |
| 150 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | memcmp(data, "RIFF", 4) != 0 || memcmp(data + 8, "WAVE", 4) != 0) |
| 151 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 152 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | while (pos + 8 <= prefix_size) { |
| 153 | 4 | uint32_t chunk_size = libmpq__load_le32(data + pos + 4); | |
| 154 | 4 | uint64_t next = (uint64_t)pos + 8 + chunk_size + (chunk_size & 1u); | |
| 155 |
3/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
|
4 | if (next < pos || next > file_size) |
| 156 | 1 | return LIBMPQ_ERROR_FORMAT; | |
| 157 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
3 | if (memcmp(data + pos, "fmt ", 4) == 0 && chunk_size >= 16) { |
| 158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if ((uint64_t)pos + 24 > prefix_size) |
| 159 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 160 | 2 | format = libmpq__load_le16(data + pos + 8); | |
| 161 | 2 | channels = libmpq__load_le16(data + pos + 10); | |
| 162 | 2 | bits = libmpq__load_le16(data + pos + 22); | |
| 163 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | } else if (memcmp(data + pos, "data", 4) == 0) { |
| 164 | 1 | data_offset = pos + 8; | |
| 165 | 1 | data_size = chunk_size; | |
| 166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if ((uint64_t)data_offset + data_size > file_size) |
| 167 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 168 | 1 | break; | |
| 169 | } | ||
| 170 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (next > prefix_size) |
| 171 | ✗ | break; | |
| 172 | 2 | pos = (uint32_t)next; | |
| 173 | } | ||
| 174 |
5/12✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
1 | if (format != 1 || (channels != 1 && channels != 2) || bits != 16 || data_offset == 0 || |
| 175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | data_offset > prefix_size || (data_size % (channels * 2)) != 0) |
| 176 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 177 | 1 | info->channels = channels; | |
| 178 | 1 | info->data_offset = data_offset; | |
| 179 | 1 | info->data_size = data_size; | |
| 180 | 1 | return LIBMPQ_SUCCESS; | |
| 181 | } | ||
| 182 | |||
| 183 | /* Encode one complete PCM sector using the MPQ mono/stereo ADPCM format. | ||
| 184 | * The first sample of each channel seeds the predictor header, and subsequent | ||
| 185 | * interleaved samples are reduced to adaptive six-bit delta codes. */ | ||
| 186 | int32_t | ||
| 187 | 7 | libmpq__wave_compress( | |
| 188 | const uint8_t *in_buf, uint32_t in_size, uint8_t **out_buf, uint32_t *out_size, | ||
| 189 | uint32_t channels | ||
| 190 | ) | ||
| 191 | { | ||
| 192 | uint32_t samples; | ||
| 193 | uint32_t i; | ||
| 194 | 7 | uint32_t shift = 4; | |
| 195 | uint32_t pos; | ||
| 196 | |||
| 197 | 7 | int32_t predictor[2] = { 0, 0 }; | |
| 198 | 7 | int32_t index[2] = { 0x2c, 0x2c }; | |
| 199 | |||
| 200 | uint8_t *out; | ||
| 201 |
6/10✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
7 | if (out_buf == NULL || out_size == NULL || in_buf == NULL || (channels != 1 && channels != 2) || |
| 202 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
7 | in_size < channels * 2 || (in_size % (channels * 2)) != 0) |
| 203 | ✗ | return LIBMPQ_ERROR_FORMAT; | |
| 204 | 7 | samples = in_size / (channels * 2); | |
| 205 | 7 | out = malloc(2 + channels * 2 + samples * channels); | |
| 206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (out == NULL) |
| 207 | ✗ | return LIBMPQ_ERROR_MALLOC; | |
| 208 | 7 | libmpq__store_le16(out, 0); | |
| 209 | 7 | out[1] = (uint8_t)shift; | |
| 210 | 7 | pos = 2; | |
| 211 | |||
| 212 | /* Store one initial predictor sample per channel in the compressed header. */ | ||
| 213 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 7 times.
|
16 | for (i = 0; i < channels; i++) { |
| 214 | 9 | predictor[i] = (int16_t)libmpq__load_le16(in_buf + i * 2); | |
| 215 | 9 | libmpq__store_le16(out + pos, (uint16_t)predictor[i]); | |
| 216 | 9 | pos += 2; | |
| 217 | } | ||
| 218 | |||
| 219 | /* Encode the remaining interleaved frames using shared channel state. */ | ||
| 220 |
2/2✓ Branch 0 taken 5995 times.
✓ Branch 1 taken 7 times.
|
6002 | for (i = 1; i < samples; i++) { |
| 221 | uint32_t channel; | ||
| 222 |
2/2✓ Branch 0 taken 6507 times.
✓ Branch 1 taken 5995 times.
|
12502 | for (channel = 0; channel < channels; channel++) { |
| 223 | 6507 | int32_t sample = (int16_t)libmpq__load_le16(in_buf + (i * channels + channel) * 2); | |
| 224 | 6507 | out[pos++] = wave_encode_delta( | |
| 225 | 6507 | sample - predictor[channel], &predictor[channel], &index[channel], shift | |
| 226 | ); | ||
| 227 | } | ||
| 228 | } | ||
| 229 | 7 | *out_buf = out; | |
| 230 | 7 | *out_size = pos; | |
| 231 | 7 | return LIBMPQ_SUCCESS; | |
| 232 | } | ||
| 233 | |||
| 234 | /* Decompress mono or stereo MPQ WAVE predictor data into PCM bytes. | ||
| 235 | * It restores channel seed samples first, then applies control and delta | ||
| 236 | * bytes until the input or caller-provided output capacity is exhausted. */ | ||
| 237 | int32_t | ||
| 238 | 7 | libmpq__wave_decompress( | |
| 239 | uint8_t *out_buf, int32_t out_length, uint8_t *in_buf, int32_t in_length, int32_t channels | ||
| 240 | ) | ||
| 241 | { | ||
| 242 | |||
| 243 | /* Decoder state for channel deltas and transferred bytes. */ | ||
| 244 | uint8_t *out_ptr; | ||
| 245 | uint32_t index; | ||
| 246 | int32_t step_indices[2]; | ||
| 247 | int32_t predictor_samples[2]; | ||
| 248 | 7 | int32_t count = 0; | |
| 249 | uint32_t shift; | ||
| 250 | |||
| 251 |
3/6✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
|
7 | if (channels < 1 || channels > 2 || in_length < 2 + channels * 2) { |
| 252 | ✗ | return 0; | |
| 253 | } | ||
| 254 | |||
| 255 | 7 | shift = in_buf[1]; | |
| 256 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
|
7 | if (shift >= 32) { |
| 257 | 2 | return 0; | |
| 258 | } | ||
| 259 | |||
| 260 | /* Stop decoding when the compressed stream cursor reaches this address. */ | ||
| 261 | 5 | uint8_t *in_end = in_buf + in_length; | |
| 262 | |||
| 263 | 5 | out_ptr = out_buf; | |
| 264 | 5 | step_indices[0] = 0x2C; | |
| 265 | 5 | step_indices[1] = 0x2C; | |
| 266 | |||
| 267 | /* The first word is the MPQ WAVE predictor header, followed by seed samples. */ | ||
| 268 | 5 | in_buf += sizeof(uint16_t); | |
| 269 | |||
| 270 | /* Emit the initial seed sample for each channel before delta decoding. */ | ||
| 271 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
|
11 | for (count = 0; count < channels; count++) { |
| 272 | |||
| 273 | /* Current sample code and output channel for this input byte. */ | ||
| 274 | int32_t temp; | ||
| 275 | |||
| 276 | 6 | temp = (int16_t)libmpq__load_le16(in_buf); | |
| 277 | 6 | in_buf += sizeof(uint16_t); | |
| 278 | 6 | predictor_samples[count] = temp; | |
| 279 | |||
| 280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (out_length < 2) { |
| 281 | ✗ | return (int32_t)(out_ptr - out_buf); | |
| 282 | } | ||
| 283 | |||
| 284 | 6 | libmpq__store_le16(out_ptr, (uint16_t)temp); | |
| 285 | 6 | out_ptr += sizeof(uint16_t); | |
| 286 | 6 | out_length -= 2; | |
| 287 | } | ||
| 288 | |||
| 289 | /* Start with the last channel so stereo data alternates on each emitted sample. */ | ||
| 290 | 5 | index = channels - 1; | |
| 291 | |||
| 292 | /* Decode interleaved control bytes until input or output capacity is exhausted. */ | ||
| 293 |
2/2✓ Branch 0 taken 5739 times.
✓ Branch 1 taken 5 times.
|
5744 | while (in_buf < in_end) { |
| 294 | 5739 | uint8_t one_byte = *in_buf++; | |
| 295 | |||
| 296 |
2/2✓ Branch 0 taken 512 times.
✓ Branch 1 taken 5227 times.
|
5739 | if (channels == 2) { |
| 297 | 512 | index = (index == 0) ? 1 : 0; | |
| 298 | } | ||
| 299 | |||
| 300 | /* High-bit control bytes adjust predictor index and do not emit samples. */ | ||
| 301 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5739 times.
|
5739 | if (one_byte & 0x80) { |
| 302 | ✗ | switch (one_byte & 0x7F) { | |
| 303 | ✗ | case 0: | |
| 304 | |||
| 305 | ✗ | if (step_indices[index] != 0) { | |
| 306 | ✗ | step_indices[index]--; | |
| 307 | } | ||
| 308 | |||
| 309 | ✗ | if (out_length < 2) { | |
| 310 | ✗ | break; | |
| 311 | } | ||
| 312 | |||
| 313 | ✗ | libmpq__store_le16(out_ptr, (uint16_t)predictor_samples[index]); | |
| 314 | ✗ | out_ptr += sizeof(uint16_t); | |
| 315 | ✗ | out_length -= 2; | |
| 316 | ✗ | continue; | |
| 317 | ✗ | case 1: | |
| 318 | |||
| 319 | ✗ | step_indices[index] += 8; | |
| 320 | |||
| 321 | ✗ | if (step_indices[index] > 0x58) { | |
| 322 | ✗ | step_indices[index] = 0x58; | |
| 323 | } | ||
| 324 | |||
| 325 | ✗ | if (channels == 2) { | |
| 326 | ✗ | index = (index == 0) ? 1 : 0; | |
| 327 | } | ||
| 328 | ✗ | continue; | |
| 329 | ✗ | case 2: | |
| 330 | ✗ | continue; | |
| 331 | ✗ | default: | |
| 332 | ✗ | step_indices[index] -= 8; | |
| 333 | |||
| 334 | ✗ | if (step_indices[index] < 0) { | |
| 335 | ✗ | step_indices[index] = 0; | |
| 336 | } | ||
| 337 | |||
| 338 | ✗ | if (channels != 2) { | |
| 339 | ✗ | continue; | |
| 340 | } | ||
| 341 | ✗ | index = (index == 0) ? 1 : 0; | |
| 342 | ✗ | continue; | |
| 343 | } | ||
| 344 | } else { | ||
| 345 | |||
| 346 | /* Low-bit values update the active channel predictor and emit PCM. */ | ||
| 347 | |||
| 348 | /* Decode a signed delta from the current step-size table entry. */ | ||
| 349 | 5739 | uint32_t temp1 = wave_step_sizes[step_indices[index]]; | |
| 350 | 5739 | uint32_t temp2 = temp1 >> shift; | |
| 351 | 5739 | int32_t temp3 = predictor_samples[index]; | |
| 352 | |||
| 353 |
2/2✓ Branch 0 taken 4480 times.
✓ Branch 1 taken 1259 times.
|
5739 | if (one_byte & 0x01) { |
| 354 | 4480 | temp2 += (temp1 >> 0); | |
| 355 | } | ||
| 356 |
2/2✓ Branch 0 taken 1236 times.
✓ Branch 1 taken 4503 times.
|
5739 | if (one_byte & 0x02) { |
| 357 | 1236 | temp2 += (temp1 >> 1); | |
| 358 | } | ||
| 359 |
2/2✓ Branch 0 taken 1237 times.
✓ Branch 1 taken 4502 times.
|
5739 | if (one_byte & 0x04) { |
| 360 | 1237 | temp2 += (temp1 >> 2); | |
| 361 | } | ||
| 362 |
2/2✓ Branch 0 taken 1247 times.
✓ Branch 1 taken 4492 times.
|
5739 | if (one_byte & 0x08) { |
| 363 | 1247 | temp2 += (temp1 >> 3); | |
| 364 | } | ||
| 365 |
2/2✓ Branch 0 taken 2427 times.
✓ Branch 1 taken 3312 times.
|
5739 | if (one_byte & 0x10) { |
| 366 | 2427 | temp2 += (temp1 >> 4); | |
| 367 | } | ||
| 368 |
2/2✓ Branch 0 taken 3286 times.
✓ Branch 1 taken 2453 times.
|
5739 | if (one_byte & 0x20) { |
| 369 | 3286 | temp2 += (temp1 >> 5); | |
| 370 | } | ||
| 371 |
2/2✓ Branch 0 taken 2890 times.
✓ Branch 1 taken 2849 times.
|
5739 | if (one_byte & 0x40) { |
| 372 | 2890 | temp3 -= temp2; | |
| 373 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2890 times.
|
2890 | if (temp3 <= (int32_t)0xFFFF8000) { |
| 374 | ✗ | temp3 = (int32_t)0xFFFF8000; | |
| 375 | } | ||
| 376 | } else { | ||
| 377 | 2849 | temp3 += temp2; | |
| 378 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2849 times.
|
2849 | if (temp3 >= 0x7FFF) { |
| 379 | ✗ | temp3 = 0x7FFF; | |
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | /* Store the clamped predictor sample for the active channel. */ | ||
| 384 | 5739 | predictor_samples[index] = temp3; | |
| 385 | |||
| 386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5739 times.
|
5739 | if (out_length < 2) { |
| 387 | ✗ | break; | |
| 388 | } | ||
| 389 | |||
| 390 | 5739 | temp2 = step_indices[index]; | |
| 391 | 5739 | one_byte &= 0x1F; | |
| 392 | 5739 | libmpq__store_le16(out_ptr, (uint16_t)temp3); | |
| 393 | 5739 | out_ptr += sizeof(uint16_t); | |
| 394 | 5739 | out_length -= 2; | |
| 395 | 5739 | temp2 += wave_step_adjustments[one_byte]; | |
| 396 | 5739 | step_indices[index] = temp2; | |
| 397 | |||
| 398 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5739 times.
|
5739 | if (step_indices[index] < 0) { |
| 399 | ✗ | step_indices[index] = 0; | |
| 400 | } else { | ||
| 401 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5739 times.
|
5739 | if (step_indices[index] > 0x58) { |
| 402 | ✗ | step_indices[index] = 0x58; | |
| 403 | } | ||
| 404 | } | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | 5 | return (int32_t)(out_ptr - out_buf); | |
| 409 | } | ||
| 410 |