void streamMusic(void* arg) { clearBottomScreen(); debug("play_buffer start\n"); stream_filename* strm_file = static_cast<stream_filename*>(arg); VGMSTREAM* vgmstream = strm_file->stream; if (!vgmstream) return; int channel = 0; ndspSetOutputMode(NDSP_OUTPUT_STEREO); for (int i = 0; i < vgmstream->channels; i++) { ndspChnReset(channel + i); ndspChnSetInterp(channel + i, NDSP_INTERP_LINEAR); ndspChnSetRate(channel + i, vgmstream->sample_rate / vgmstream->channels); ndspChnSetFormat(channel + i, NDSP_FORMAT_STEREO_PCM16); } std::vector<ndspWaveBuf> waveBufs1(vgmstream->channels); std::vector<ndspWaveBuf> waveBufs2(vgmstream->channels); for (auto& waveBuf : waveBufs1) memset(&waveBuf, 0, sizeof(ndspWaveBuf)); for (auto& waveBuf : waveBufs2) memset(&waveBuf, 0, sizeof(ndspWaveBuf)); debug("play_buffer signal produce\n"); svcSignalEvent(bufferReadyProduceRequest); // Wait for 2 buffers to play debug("play_buffer wait data 1\n"); svcWaitSynchronization(bufferReadyConsumeRequest, U64_MAX); svcClearEvent(bufferReadyConsumeRequest); debug("play_buffer signal produce\n"); svcSignalEvent(bufferReadyProduceRequest); debug("play_buffer wait data 2\n"); svcWaitSynchronization(bufferReadyConsumeRequest, U64_MAX); svcClearEvent(bufferReadyConsumeRequest); // Play it debug("play_buffer play\n"); playSoundChannels(channel, playBuffer1.samples, false, playBuffer1.channels, waveBufs1); playSoundChannels(channel, playBuffer2.samples, false, playBuffer2.channels, waveBufs2); stream_buffer* buffer = &playBuffer2; stream_buffer* playingBuf = &playBuffer1; std::vector<ndspWaveBuf>* waveBuf = &waveBufs2; std::vector<ndspWaveBuf>* playingWaveBuf = &waveBufs1; debug("play_buffer signal produce\n"); svcSignalEvent(bufferReadyProduceRequest); while (runThreads) { if (playingWaveBuf->at(0).status == NDSP_WBUF_DONE) { debug("play_buffer wait data\n"); // Wait for sound data here svcWaitSynchronization(bufferReadyConsumeRequest, U64_MAX); svcClearEvent(bufferReadyConsumeRequest); // Flip buffers if (buffer == &playBuffer1) { buffer = &playBuffer2; playingBuf = &playBuffer1; waveBuf = &waveBufs2; playingWaveBuf = &waveBufs1; } else { buffer = &playBuffer1; playingBuf = &playBuffer2; waveBuf = &waveBufs1; playingWaveBuf = &waveBufs2; } debug("play_buffer play\n"); playSoundChannels(channel, buffer->samples, false, buffer->channels, *waveBuf); debug("play_buffer signal produce\n"); svcSignalEvent(bufferReadyProduceRequest); } } for (int i = 0; i < vgmstream->channels; i++) { ndspChnWaveBufClear(channel + i); } debug("play_buffer done\n"); }
//---------------------------------------------------------------------------- int main(int argc, char **argv) { //---------------------------------------------------------------------------- PrintConsole topScreen; ndspWaveBuf waveBuf[2]; gfxInitDefault(); consoleInit(GFX_TOP, &topScreen); consoleSelect(&topScreen); printf("libctru streaming audio\n"); stb_vorbis_info info; int error; vorbisFile = stb_vorbis_open_filename("/mau5.ogg", &error, NULL); info = stb_vorbis_get_info(vorbisFile); Samples = info.sample_rate; u32 *audioBuffer = (u32*)linearAlloc(Samples*sizeof(s16)*2); bool fillBlock = false; ndspInit(); ndspSetOutputMode(NDSP_OUTPUT_STEREO); ndspChnSetInterp(0, NDSP_INTERP_LINEAR); ndspChnSetRate(0, Samples); ndspChnSetFormat(0, NDSP_FORMAT_STEREO_PCM16); float mix[12]; memset(mix, 0, sizeof(mix)); mix[0] = 1.0; mix[1] = 1.0; ndspChnSetMix(0, mix); int note = 4; memset(waveBuf,0,sizeof(waveBuf)); waveBuf[0].data_vaddr = &audioBuffer[0]; waveBuf[0].nsamples = Samples; waveBuf[1].data_vaddr = &audioBuffer[Samples]; waveBuf[1].nsamples = Samples; ndspChnWaveBufAdd(0, &waveBuf[0]); ndspChnWaveBufAdd(0, &waveBuf[1]); printf("Press up/down to change tone\n"); while(aptMainLoop()) { gfxSwapBuffers(); gfxFlushBuffers(); gspWaitForVBlank(); hidScanInput(); u32 kDown = hidKeysDown(); if (kDown & KEY_START) break; // break in order to return to hbmenu if (waveBuf[fillBlock].status == NDSP_WBUF_DONE) { fill_buffer(waveBuf[fillBlock].data_pcm16, waveBuf[fillBlock].nsamples); ndspChnWaveBufAdd(0, &waveBuf[fillBlock]); fillBlock = !fillBlock; } } ndspExit(); linearFree(audioBuffer); gfxExit(); return 0; }