Ogg Vorbis/Opus: Use correct channel output order for surround files

CQTexperiment
Christopher Snowhill 2021-12-28 00:54:28 -08:00
parent b13235ec5f
commit 73a356ad1d
2 changed files with 49 additions and 5 deletions

View File

@ -14,6 +14,18 @@
@implementation OpusFile
static const int MAXCHANNELS = 8;
static const int chmap[MAXCHANNELS][MAXCHANNELS] = {
{ 0, }, // mono
{ 0, 1, }, // l, r
{ 0, 2, 1, }, // l, c, r -> l, r, c
{ 0, 1, 2, 3, }, // l, r, bl, br
{ 0, 2, 1, 3, 4, }, // l, c, r, bl, br -> l, r, c, bl, br
{ 0, 2, 1, 5, 3, 4 }, // l, c, r, bl, br, lfe -> l, r, c, lfe, bl, br
{ 0, 2, 1, 6, 5, 3, 4 }, // l, c, r, sl, sr, bc, lfe -> l, r, c, lfe, bc, sl, sr
{ 0, 2, 1, 7, 5, 6, 3, 4 } // l, c, r, sl, sr, bl, br, lfe -> l, r, c, lfe, bl, br, sl, sr
};
int sourceRead(void *_stream, unsigned char *_ptr, int _nbytes)
{
id source = (__bridge id)_stream;
@ -100,8 +112,19 @@ opus_int64 sourceTell(void *_stream)
int size = frames * channels;
do {
float *out = ((float*)buf) + total;
float tempbuf[512 * channels];
lastSection = currentSection;
numread = op_read_float( opusRef, &((float *)buf)[total], size - total, NULL );
int toread = size - total;
if (toread > 512) toread = 512;
numread = op_read_float( opusRef, (channels < MAXCHANNELS) ? tempbuf : out, toread, NULL );
if (numread > 0 && channels < MAXCHANNELS) {
for (int i = 0; i < numread; ++i) {
for (int j = 0; j < channels; ++j) {
out[i * channels + j] = tempbuf[i * channels + chmap[channels - 1][j]];
}
}
}
currentSection = op_current_link( opusRef );
if (numread > 0) {
total += numread * channels;
@ -111,7 +134,7 @@ opus_int64 sourceTell(void *_stream)
break;
}
} while (total != frames && numread != 0);
} while (total != size && numread != 0);
return total/channels;
}

View File

@ -12,6 +12,18 @@
@implementation VorbisDecoder
static const int MAXCHANNELS = 8;
static const int chmap[MAXCHANNELS][MAXCHANNELS] = {
{ 0, }, // mono
{ 0, 1, }, // l, r
{ 0, 2, 1, }, // l, c, r -> l, r, c
{ 0, 1, 2, 3, }, // l, r, bl, br
{ 0, 2, 1, 3, 4, }, // l, c, r, bl, br -> l, r, c, bl, br
{ 0, 2, 1, 5, 3, 4 }, // l, c, r, bl, br, lfe -> l, r, c, lfe, bl, br
{ 0, 2, 1, 6, 5, 3, 4 }, // l, c, r, sl, sr, bc, lfe -> l, r, c, lfe, bc, sl, sr
{ 0, 2, 1, 7, 5, 6, 3, 4 } // l, c, r, sl, sr, bl, br, lfe -> l, r, c, lfe, bl, br, sl, sr
};
size_t sourceRead(void *buf, size_t size, size_t nmemb, void *datasource)
{
id source = (__bridge id)datasource;
@ -94,9 +106,18 @@ long sourceTell(void *datasource)
float ** pcm;
numread = (int)ov_read_float(&vorbisRef, &pcm, frames - total, &currentSection);
if (numread > 0) {
for (int i = 0; i < channels; i++) {
for (int j = 0; j < numread; j++) {
((float *)buf)[(total + j) * channels + i] = pcm[i][j];
if (channels < MAXCHANNELS) {
for (int i = 0; i < channels; i++) {
for (int j = 0; j < numread; j++) {
((float *)buf)[(total + j) * channels + i] = pcm[chmap[channels-1][i]][j];
}
}
}
else {
for (int i = 0; i < channels; i++) {
for (int j = 0; j < numread; j++) {
((float *)buf)[(total + j) * channels + i] = pcm[i][j];
}
}
}
total += numread;