Files
mice-3ds/source/playback.c
Mahyar Koshkouei 644e501d6e Refactor Opus decoder
Created generic playback handler, first with Opus support. Other
decoders to follow. This is to remove duplicated code.

3DSX tested working with citra and N3DS.

Signed-off-by: Mahyar Koshkouei <deltabeard@users.noreply.github.com>
2017-01-12 11:48:48 +00:00

139 lines
3.1 KiB
C

#include <3ds.h>
#include <stdlib.h>
#include <string.h>
#include "all.h"
#include "opus.h"
#include "playback.h"
int playFile(const char* file)
{
struct decoder_fn decoder;
int16_t* buffer1 = NULL;
int16_t* buffer2 = NULL;
ndspWaveBuf waveBuf[2];
bool playing = true;
bool lastbuf = false;
printf("Here: %d\n", __LINE__);
if(R_FAILED(ndspInit()))
{
printf("Initialising ndsp failed.");
goto out;
}
printf("Here: %d\n", __LINE__);
setOpus(&decoder);
printf("Here: %d\n", __LINE__);
buffer1 = linearAlloc(decoder.buffSize * sizeof(int16_t));
buffer2 = linearAlloc(decoder.buffSize * sizeof(int16_t));
printf("Here: %d\n", __LINE__);
if((*decoder.init)(file) != 0)
goto out;
printf("Here: %d\n", __LINE__);
#ifdef DEBUG
printf("\nRate: %lu\tChan: %d\n", (*decoder.rate)(), decoder.channels);
#endif
ndspChnReset(CHANNEL);
ndspChnWaveBufClear(CHANNEL);
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
ndspChnSetInterp(CHANNEL, NDSP_INTERP_POLYPHASE);
ndspChnSetRate(CHANNEL, (*decoder.rate)());
ndspChnSetFormat(CHANNEL, NDSP_FORMAT_STEREO_PCM16);
printf("Here: %d\n", __LINE__);
memset(waveBuf, 0, sizeof(waveBuf));
waveBuf[0].nsamples = (*decoder.decode)(&buffer1[0]) / decoder.channels;
waveBuf[0].data_vaddr = &buffer1[0];
ndspChnWaveBufAdd(CHANNEL, &waveBuf[0]);
printf("Here: %d\n", __LINE__);
waveBuf[1].nsamples = (*decoder.decode)(&buffer2[0]) / decoder.channels;
waveBuf[1].data_vaddr = &buffer2[0];
ndspChnWaveBufAdd(CHANNEL, &waveBuf[1]);
printf("Playing %s\n", file);
/**
* There may be a chance that the music has not started by the time we get
* to the while loop. So we ensure that music has started here.
*/
while(ndspChnIsPlaying(CHANNEL) == false);
while(playing == false || ndspChnIsPlaying(CHANNEL) == true)
{
u32 kDown;
/* Number of bytes read from file.
* Static only for the purposes of the printf debug at the bottom.
*/
static size_t read = 0;
gfxSwapBuffers();
gfxFlushBuffers();
gspWaitForVBlank();
hidScanInput();
kDown = hidKeysDown();
if(kDown & KEY_B)
break;
if(kDown & (KEY_A | KEY_R))
{
playing = !playing;
printf("\33[2K\r%s", playing == false ? "Paused" : "");
}
if(playing == false || lastbuf == true)
continue;
if(waveBuf[0].status == NDSP_WBUF_DONE)
{
read = (*decoder.decode)(&buffer1[0]);
if(read == 0)
{
lastbuf = true;
continue;
}
else if(read < decoder.buffSize)
waveBuf[0].nsamples = read / decoder.channels;
ndspChnWaveBufAdd(CHANNEL, &waveBuf[0]);
}
if(waveBuf[1].status == NDSP_WBUF_DONE)
{
read = (*decoder.decode)(&buffer2[0]);
if(read == 0)
{
lastbuf = true;
continue;
}
else if(read < decoder.buffSize)
waveBuf[1].nsamples = read / decoder.channels;
ndspChnWaveBufAdd(CHANNEL, &waveBuf[1]);
}
DSP_FlushDataCache(buffer1, decoder.buffSize * sizeof(int16_t));
DSP_FlushDataCache(buffer2, decoder.buffSize * sizeof(int16_t));
}
out:
printf("\nStopping playback.\n");
(*decoder.exit)();
ndspChnWaveBufClear(CHANNEL);
ndspExit();
linearFree(buffer1);
linearFree(buffer2);
return 0;
}