mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-12-20 18:35:52 +01:00
97ebe328c8
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@292 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
130 lines
4.2 KiB
C
130 lines
4.2 KiB
C
#include "../vgmstream.h"
|
|
|
|
#ifdef VGM_USE_MPEG
|
|
#include <string.h>
|
|
#include <mpg123.h>
|
|
#include "coding.h"
|
|
#include "../util.h"
|
|
|
|
/* mono, mpg123 expects frames of 0x414 (160kbps, 22050Hz) but they
|
|
* actually vary and are much shorter */
|
|
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream,
|
|
mpeg_codec_data * data,
|
|
sample * outbuf, int32_t samples_to_do) {
|
|
int samples_done = 0;
|
|
|
|
while (samples_done < samples_to_do) {
|
|
size_t bytes_done;
|
|
int rc;
|
|
|
|
if (!data->buffer_full) {
|
|
/* fill buffer up to next frame ending (or file ending) */
|
|
int bytes_into_header = 0;
|
|
const uint8_t header[4] = {0xff,0xf5,0xe0,0xc0};
|
|
off_t frame_offset = 0;
|
|
|
|
/* assume that we are starting at a header, skip it and look for the
|
|
* next one */
|
|
read_streamfile(data->buffer, stream->offset+frame_offset, 4,
|
|
stream->streamfile);
|
|
frame_offset += 4;
|
|
|
|
do {
|
|
uint8_t byte;
|
|
byte =
|
|
read_8bit(stream->offset+frame_offset,stream->streamfile);
|
|
data->buffer[frame_offset] = byte;
|
|
frame_offset++;
|
|
|
|
if (byte == header[bytes_into_header]) {
|
|
bytes_into_header++;
|
|
} else {
|
|
/* This might have been the first byte of the header, so
|
|
* we need to check again.
|
|
* No need to get more complicated than this, though, since
|
|
* there are no repeated characters in the search string. */
|
|
if (bytes_into_header>0) {
|
|
frame_offset--;
|
|
}
|
|
bytes_into_header=0;
|
|
}
|
|
|
|
if (bytes_into_header==4) {
|
|
break;
|
|
}
|
|
} while (frame_offset < AHX_EXPECTED_FRAME_SIZE);
|
|
|
|
if (bytes_into_header==4) frame_offset-=4;
|
|
memset(data->buffer+frame_offset,0,
|
|
AHX_EXPECTED_FRAME_SIZE-frame_offset);
|
|
|
|
data->buffer_full = 1;
|
|
data->buffer_used = 0;
|
|
|
|
stream->offset += frame_offset;
|
|
}
|
|
|
|
if (!data->buffer_used) {
|
|
rc = mpg123_decode(data->m,
|
|
data->buffer,AHX_EXPECTED_FRAME_SIZE,
|
|
(unsigned char *)(outbuf+samples_done),
|
|
(samples_to_do-samples_done)*sizeof(sample),
|
|
&bytes_done);
|
|
data->buffer_used = 1;
|
|
} else {
|
|
rc = mpg123_decode(data->m,
|
|
NULL,0,
|
|
(unsigned char *)(outbuf+samples_done),
|
|
(samples_to_do-samples_done)*sizeof(sample),
|
|
&bytes_done);
|
|
}
|
|
|
|
if (rc == MPG123_NEED_MORE) data->buffer_full = 0;
|
|
|
|
samples_done += bytes_done/sizeof(sample);
|
|
}
|
|
}
|
|
|
|
/* decode anything mpg123 can */
|
|
void decode_mpeg(VGMSTREAMCHANNEL *stream,
|
|
mpeg_codec_data * data,
|
|
sample * outbuf, int32_t samples_to_do, int channels) {
|
|
int samples_done = 0;
|
|
|
|
while (samples_done < samples_to_do) {
|
|
size_t bytes_done;
|
|
int rc;
|
|
|
|
if (!data->buffer_full) {
|
|
data->bytes_in_buffer = read_streamfile(data->buffer,
|
|
stream->offset,MPEG_BUFFER_SIZE,stream->streamfile);
|
|
|
|
data->buffer_full = 1;
|
|
data->buffer_used = 0;
|
|
|
|
stream->offset += data->bytes_in_buffer;
|
|
}
|
|
|
|
if (!data->buffer_used) {
|
|
rc = mpg123_decode(data->m,
|
|
data->buffer,data->bytes_in_buffer,
|
|
(unsigned char *)(outbuf+samples_done*channels),
|
|
(samples_to_do-samples_done)*sizeof(sample)*channels,
|
|
&bytes_done);
|
|
data->buffer_used = 1;
|
|
} else {
|
|
rc = mpg123_decode(data->m,
|
|
NULL,0,
|
|
(unsigned char *)(outbuf+samples_done*channels),
|
|
(samples_to_do-samples_done)*sizeof(sample)*channels,
|
|
&bytes_done);
|
|
}
|
|
|
|
if (rc == MPG123_NEED_MORE) data->buffer_full = 0;
|
|
|
|
samples_done += bytes_done/sizeof(sample)/channels;
|
|
}
|
|
}
|
|
|
|
#endif
|