* This does the main decoding thing. * Requires an already opened WavpackContext. */
| 168 | * Requires an already opened WavpackContext. |
| 169 | */ |
| 170 | static void |
| 171 | wavpack_decode(DecoderClient &client, WavpackContext *wpc, bool can_seek) |
| 172 | { |
| 173 | const auto audio_format = CheckAudioFormat(wpc); |
| 174 | |
| 175 | auto *format_samples = format_samples_nop; |
| 176 | if (audio_format.format == SampleFormat::DSD) |
| 177 | format_samples = format_samples_int<uint8_t>; |
| 178 | else if (audio_format.format != SampleFormat::FLOAT) { |
| 179 | switch (WavpackGetBytesPerSample(wpc)) { |
| 180 | case 1: |
| 181 | format_samples = format_samples_int<int8_t>; |
| 182 | break; |
| 183 | |
| 184 | case 2: |
| 185 | format_samples = format_samples_int<int16_t>; |
| 186 | break; |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | client.Ready(audio_format, can_seek, GetDuration(wpc)); |
| 191 | |
| 192 | const std::size_t output_frame_size = audio_format.GetFrameSize(); |
| 193 | |
| 194 | /* wavpack gives us all kind of samples in a 32-bit space */ |
| 195 | int32_t buffer[1024]; |
| 196 | const uint32_t max_frames = std::size(buffer) / audio_format.channels; |
| 197 | |
| 198 | DecoderCommand cmd = client.GetCommand(); |
| 199 | while (cmd != DecoderCommand::STOP) { |
| 200 | if (cmd == DecoderCommand::SEEK) { |
| 201 | if (can_seek) { |
| 202 | auto where = client.GetSeekFrame(); |
| 203 | if (!WavpackSeekSample64(wpc, where)) { |
| 204 | /* seek errors are fatal */ |
| 205 | client.SeekError(); |
| 206 | break; |
| 207 | } |
| 208 | |
| 209 | client.CommandFinished(); |
| 210 | } else { |
| 211 | client.SeekError(); |
| 212 | } |
| 213 | } |
| 214 | |
| 215 | uint32_t n_frames = WavpackUnpackSamples(wpc, buffer, |
| 216 | max_frames); |
| 217 | if (n_frames == 0) |
| 218 | break; |
| 219 | |
| 220 | int bitrate = lround(WavpackGetInstantBitrate(wpc) / 1000); |
| 221 | format_samples(buffer, n_frames * audio_format.channels); |
| 222 | |
| 223 | cmd = client.SubmitAudio(nullptr, |
| 224 | { |
| 225 | (const std::byte *)buffer, |
| 226 | n_frames * output_frame_size, |
| 227 | }, |
no test coverage detected