summaryrefslogtreecommitdiff
path: root/plugins/vorbis
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/vorbis')
-rw-r--r--plugins/vorbis/vorbis.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index 250c8bac..390e614e 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -252,9 +252,10 @@ static int
cvorbis_read (DB_fileinfo_t *_info, char *bytes, int size) {
ogg_info_t *info = (ogg_info_t *)_info;
// trace ("cvorbis_read %d bytes\n", size);
+ int out_ch = min (_info->channels, 2);
if (!info->info.file->vfs->streaming) {
- if (info->currentsample + size / (2 * _info->channels) > info->endsample) {
- size = (info->endsample - info->currentsample + 1) * 2 * _info->channels;
+ if (info->currentsample + size / (2 * out_ch) > info->endsample) {
+ size = (info->endsample - info->currentsample + 1) * 2 * out_ch;
trace ("size truncated to %d bytes, cursample=%d, info->endsample=%d, totalsamples=%d\n", size, info->currentsample, info->endsample, ov_pcm_total (&info->vorbis_file, -1));
if (size <= 0) {
return 0;
@@ -284,7 +285,24 @@ cvorbis_read (DB_fileinfo_t *_info, char *bytes, int size) {
#if WORDS_BIGENDIAN
endianess = 1;
#endif
- ret=ov_read (&info->vorbis_file, bytes, size, endianess, 2, 1, &info->cur_bit_stream);
+
+ if (out_ch != _info->channels) {
+ int nframes = size / out_ch / 2;
+ int16_t buf[nframes * _info->channels];
+ ret=ov_read (&info->vorbis_file, (char*)buf, sizeof(buf), endianess, 2, 1, &info->cur_bit_stream);
+ if (ret > 0) {
+ int n = ret / _info->channels / 2;
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < out_ch; j++) {
+ ((int16_t *)bytes)[i * out_ch + j] = buf[i * _info->channels + j];
+ }
+ }
+ ret = n * out_ch * 2;
+ }
+ }
+ else {
+ ret=ov_read (&info->vorbis_file, bytes, size, endianess, 2, 1, &info->cur_bit_stream);
+ }
if (ret <= 0)
{
if (ret < 0) {
@@ -309,12 +327,12 @@ cvorbis_read (DB_fileinfo_t *_info, char *bytes, int size) {
}
else if (ret < size)
{
- info->currentsample += ret / (info->vi->channels * 2);
+ info->currentsample += ret / (out_ch * 2);
size -= ret;
bytes += ret;
}
else {
- info->currentsample += ret / (info->vi->channels * 2);
+ info->currentsample += ret / (out_ch * 2);
size = 0;
break;
}