Add working Opus file support

Opus files can now be played.
Fixed an issue where monophonic tracks were being played twice as slow.
Opus decodes to stereo always.
Additionally added ability to loop the file selector from 1 to the last
file when pressing down and vice versa.

There are known issues. Please see the issues page for them.

Tested working with:
196kbit Stereo Opus File
32kbit Stereo Opus File
96kbit Mono Opus File
8kbit Stereo Opus File

Signed-off-by: Mahyar Koshkouei <deltabeard@users.noreply.github.com>
This commit is contained in:
Mahyar Koshkouei
2016-12-28 12:07:09 +00:00
parent 3c99a80581
commit 56d5c7d760
2 changed files with 22 additions and 27 deletions

View File

@@ -99,11 +99,22 @@ int main(int argc, char **argv)
if(kDown & KEY_START)
break;
if(kDown & KEY_UP && fileNum < fileMax)
printf("\33[2K\rSelected file %d", ++fileNum);
if(kDown & KEY_UP)
{
printf("\33[2K\rSelected file %d",
++fileNum > fileMax ? 1 : fileNum);
}
if(kDown & KEY_DOWN && fileNum > 1)
printf("\33[2K\rSelected file %d", --fileNum);
if(kDown & KEY_DOWN)
{
printf("\33[2K\rSelected file %d",
--fileNum == 0 ? fileMax : fileNum);
}
if(fileNum == 0)
fileNum = fileMax;
else if(fileNum > fileMax)
fileNum = 1;
if(kDown & (KEY_A | KEY_R))
{

View File

@@ -11,8 +11,8 @@
int playOpus(const char* in)
{
int err = 0;
s16* buffer1 = linearAlloc(SAMPLES_TO_READ * sizeof(s16));
s16* buffer2 = linearAlloc(SAMPLES_TO_READ * sizeof(s16));
int16_t* buffer1 = linearAlloc(SAMPLES_TO_READ * sizeof(int16_t));
int16_t* buffer2 = linearAlloc(SAMPLES_TO_READ * sizeof(int16_t));
ndspWaveBuf waveBuf[2];
bool playing = true;
bool lastbuf = false;
@@ -47,17 +47,16 @@ int playOpus(const char* in)
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
ndspChnSetInterp(CHANNEL, NDSP_INTERP_POLYPHASE);
ndspChnSetRate(CHANNEL, opusHead->input_sample_rate);
ndspChnSetFormat(CHANNEL, opusHead->channel_count == 2 ? NDSP_FORMAT_STEREO_PCM16 :
NDSP_FORMAT_MONO_PCM16);
ndspChnSetFormat(CHANNEL, NDSP_FORMAT_STEREO_PCM16);
memset(waveBuf, 0, sizeof(waveBuf));
waveBuf[0].nsamples =
fillOpusBuffer(opusFile, SAMPLES_TO_READ, buffer1) / opusHead->channel_count;
fillOpusBuffer(opusFile, SAMPLES_TO_READ, buffer1) / 2;
waveBuf[0].data_vaddr = &buffer1[0];
ndspChnWaveBufAdd(CHANNEL, &waveBuf[0]);
waveBuf[1].nsamples =
fillOpusBuffer(opusFile, SAMPLES_TO_READ, buffer1) / opusHead->channel_count;
fillOpusBuffer(opusFile, SAMPLES_TO_READ, buffer2) / 2;
waveBuf[1].data_vaddr = &buffer2[0];
ndspChnWaveBufAdd(CHANNEL, &waveBuf[1]);
@@ -155,19 +154,16 @@ out:
uint64_t fillOpusBuffer(OggOpusFile* opusFile, uint64_t samplesToRead,
int16_t* bufferOut)
{
uint64_t samplesRead = 0;
opus_int16* pcm = malloc(120 * 48 * 2 * sizeof(opus_int16));
opus_int16* out = malloc(120 * 48 * 2 * 2 * sizeof(opus_int16));
uint64_t samplesRead = 0;
while(samplesToRead > 0)
{
uint64_t samplesJustRead = op_read_stereo(opusFile, pcm,
uint64_t samplesJustRead = op_read_stereo(opusFile, bufferOut,
samplesToRead > 120*48*2 ? 120*48*2 : samplesToRead);
if(samplesJustRead < 0)
{
printf("\nFatal error decoding Opus: %llu.", samplesJustRead);
free(pcm);
return 0;
}
else if(samplesJustRead == 0)
@@ -176,23 +172,11 @@ uint64_t fillOpusBuffer(OggOpusFile* opusFile, uint64_t samplesToRead,
break;
}
for(int si = 0; si < 2 * samplesJustRead; si++)
{
out[2*si*0] = (pcm[si] & 0xFF);
out[2*si*1] = (pcm[si] >> 8&0xFF);
}
for(uint64_t i = 0; i < samplesJustRead * 2; ++i)
{
bufferOut[i] = out[i];
}
samplesRead += samplesJustRead * 2;
samplesToRead -= samplesJustRead * 2;
bufferOut += samplesJustRead * 2;
}
free(pcm);
return samplesRead;
}