mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-10 08:03:04 -04:00
wma: decode every codec packet in an ASF payload
A payload normally holds one codec packet of blockalign bytes, but
some files put several in each. Only the first was decoded, so such
a file played one packet in every 8 or 15, as a few seconds of
broken sound, and then ended.
Step through the payload in blockalign sized packets.
Checked with perfsim (Sansa e200v1 build) against ffmpeg's decode:
doors-test.wma (WMA v2, 11 kHz mono), 15 packets a payload:
80896 of 1205760 samples before, all of them after, 86 dB SNR
test.wma (WMA v1, 44.1 kHz stereo), 8 packets a payload:
1294336 of 10346496 samples before, all after, 114 dB SNR
The output of 26 other WMA files is byte-identical before and after.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6ffbee954b
commit
fb2ee6c08f
1 changed files with 31 additions and 18 deletions
|
|
@ -178,29 +178,42 @@ new_packet:
|
||||||
goto new_packet;
|
goto new_packet;
|
||||||
}
|
}
|
||||||
} else if (res > 0) {
|
} else if (res > 0) {
|
||||||
wma_decode_superframe_init(&wmadec, audiobuf, audiobufsize);
|
/* A payload usually holds one codec packet (a superframe) of
|
||||||
|
* blockalign bytes, but it can hold several. */
|
||||||
|
int packetsize = audiobufsize;
|
||||||
|
int offset;
|
||||||
|
|
||||||
for (i=0; i < wmadec.nb_frames; i++)
|
if (wfx.blockalign > 0 && audiobufsize % wfx.blockalign == 0)
|
||||||
|
packetsize = wfx.blockalign;
|
||||||
|
|
||||||
|
for (offset = 0; offset < audiobufsize; offset += packetsize)
|
||||||
{
|
{
|
||||||
wmares = wma_decode_superframe_frame(&wmadec,
|
const uint8_t *packet = audiobuf + offset;
|
||||||
audiobuf, audiobufsize);
|
|
||||||
|
|
||||||
ci->yield ();
|
wma_decode_superframe_init(&wmadec, packet, packetsize);
|
||||||
|
|
||||||
if (wmares < 0) {
|
for (i=0; i < wmadec.nb_frames; i++)
|
||||||
/* Do the above, but for errors in decode. */
|
{
|
||||||
errcount++;
|
wmares = wma_decode_superframe_frame(&wmadec,
|
||||||
DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount);
|
packet, packetsize);
|
||||||
if (errcount > 5) {
|
|
||||||
return CODEC_ERROR;
|
ci->yield ();
|
||||||
} else {
|
|
||||||
ci->advance_buffer(packetlength);
|
if (wmares < 0) {
|
||||||
goto new_packet;
|
/* Do the above, but for errors in decode. */
|
||||||
|
errcount++;
|
||||||
|
DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount);
|
||||||
|
if (errcount > 5) {
|
||||||
|
return CODEC_ERROR;
|
||||||
|
} else {
|
||||||
|
ci->advance_buffer(packetlength);
|
||||||
|
goto new_packet;
|
||||||
|
}
|
||||||
|
} else if (wmares > 0) {
|
||||||
|
ci->pcmbuf_insert((*wmadec.frame_out)[0], (*wmadec.frame_out)[1], wmares);
|
||||||
|
elapsedtime += (wmares*10)/(wfx.rate/100);
|
||||||
|
ci->set_elapsed(elapsedtime);
|
||||||
}
|
}
|
||||||
} else if (wmares > 0) {
|
|
||||||
ci->pcmbuf_insert((*wmadec.frame_out)[0], (*wmadec.frame_out)[1], wmares);
|
|
||||||
elapsedtime += (wmares*10)/(wfx.rate/100);
|
|
||||||
ci->set_elapsed(elapsedtime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue