audio/streaming/source/main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <3ds.h>
#define SAMPLERATE 22050
#define SAMPLESPERBUF (SAMPLERATE / 30)
#define BYTESPERSAMPLE 4
//----------------------------------------------------------------------------
void fill_buffer(void *audioBuffer,size_t offset, size_t size, int frequency ) {
//----------------------------------------------------------------------------
u32 *dest = (u32*)audioBuffer;
for (int i=0; i<size; i++) {
s16 sample = INT16_MAX * sin(frequency*(2*M_PI)*(offset+i)/SAMPLERATE);
dest[i] = (sample<<16) | (sample & 0xffff);
}
DSP_FlushDataCache(audioBuffer,size);
}
//----------------------------------------------------------------------------
int main(int argc, char **argv) {
//----------------------------------------------------------------------------
PrintConsole topScreen;
ndspWaveBuf waveBuf[2];
gfxInitDefault();
consoleInit(GFX_TOP, &topScreen);
consoleSelect(&topScreen);
printf("libctru streaming audio\n");
u32 *audioBuffer = (u32*)linearAlloc(SAMPLESPERBUF*BYTESPERSAMPLE*2);
bool fillBlock = false;
ndspInit();
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
ndspChnSetInterp(0, NDSP_INTERP_LINEAR);
ndspChnSetRate(0, SAMPLERATE);
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 notefreq[] = {
262, 294, 339, 349, 392, 440,
494, 440, 392, 349, 339, 294
};
int note = 4;
memset(waveBuf,0,sizeof(waveBuf));
waveBuf[0].data_vaddr = &audioBuffer[0];
waveBuf[0].nsamples = SAMPLESPERBUF;
waveBuf[1].data_vaddr = &audioBuffer[SAMPLESPERBUF];
waveBuf[1].nsamples = SAMPLESPERBUF;
size_t stream_offset = 0;
fill_buffer(audioBuffer,stream_offset, SAMPLESPERBUF * 2, notefreq[note]);
stream_offset += SAMPLESPERBUF;
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 (kDown & KEY_DOWN) {
note -= 1;
if (note<0) note = sizeof(notefreq)/sizeof(notefreq[0])-1;
}
if (kDown & KEY_UP) {
note += 1;
if (note > (sizeof(notefreq)/sizeof(notefreq[0])-1)) note = 0;
}
if (waveBuf[fillBlock].status == NDSP_WBUF_DONE) {
fill_buffer(waveBuf[fillBlock].data_pcm16, stream_offset, waveBuf[fillBlock].nsamples,notefreq[note]);
ndspChnWaveBufAdd(0, &waveBuf[fillBlock]);
stream_offset += waveBuf[fillBlock].nsamples;
fillBlock = !fillBlock;
}
}
ndspExit();
linearFree(audioBuffer);
gfxExit();
return 0;
}
3ds.h
Central 3DS header.
aptMainLoop
bool aptMainLoop(void)
Main function which handles sleep mode and HOME/power buttons - call this at the beginning of every f...
NDSP_FORMAT_STEREO_PCM16
@ NDSP_FORMAT_STEREO_PCM16
Buffer contains Stereo PCM16.
Definition: channel.h:29
ndspChnSetMix
void ndspChnSetMix(int id, float mix[12])
Sets the mix parameters (volumes) of a channel.
ndspChnWaveBufAdd
void ndspChnWaveBufAdd(int id, ndspWaveBuf *buf)
Adds a wave buffer to the wave buffer queue of a channel.
NDSP_INTERP_LINEAR
@ NDSP_INTERP_LINEAR
Linear interpolation.
Definition: channel.h:44
ndspChnSetRate
void ndspChnSetRate(int id, float rate)
Sets the sample rate of a channel.
ndspChnSetFormat
void ndspChnSetFormat(int id, u16 format)
Sets the format of a channel.
ndspChnSetInterp
void ndspChnSetInterp(int id, ndspInterpType type)
Sets the interpolation type of a channel.
consoleInit
PrintConsole * consoleInit(gfxScreen_t screen, PrintConsole *console)
Initialise the console.
consoleSelect
PrintConsole * consoleSelect(PrintConsole *console)
Make the specified console the render target.
DSP_FlushDataCache
Result DSP_FlushDataCache(const void *address, u32 size)
Flushes the cache.
gfxSwapBuffers
void gfxSwapBuffers(void)
Updates the configuration of both screens.
gfxInitDefault
void gfxInitDefault(void)
Initializes the LCD framebuffers with default parameters This is equivalent to calling:
GFX_TOP
@ GFX_TOP
Top screen.
Definition: gfx.h:26
gfxExit
void gfxExit(void)
Deinitializes and frees the LCD framebuffers.
gfxFlushBuffers
void gfxFlushBuffers(void)
Flushes the data cache for the current framebuffers.
gspWaitForVBlank
#define gspWaitForVBlank()
Waits for VBlank.
Definition: gspgpu.h:151
KEY_UP
@ KEY_UP
D-Pad Up or Circle Pad Up.
Definition: hid.h:37
KEY_START
@ KEY_START
Start.
Definition: hid.h:15
KEY_DOWN
@ KEY_DOWN
D-Pad Down or Circle Pad Down.
Definition: hid.h:38
hidKeysDown
u32 hidKeysDown(void)
Returns a bitmask of newly pressed buttons, this frame.
hidScanInput
void hidScanInput(void)
Scans HID for input data.
linearAlloc
void * linearAlloc(size_t size)
Allocates a 0x80-byte aligned buffer.
linearFree
void linearFree(void *mem)
Frees a buffer.
ndspSetOutputMode
void ndspSetOutputMode(ndspOutputMode mode)
Sets the output mode.
NDSP_WBUF_DONE
@ NDSP_WBUF_DONE
The wave buffer has finished being played.
Definition: ndsp.h:53
ndspExit
void ndspExit(void)
Exits NDSP.
NDSP_OUTPUT_STEREO
@ NDSP_OUTPUT_STEREO
Stereo sound.
Definition: ndsp.h:17
ndspInit
Result ndspInit(void)
Initializes NDSP.
PrintConsole
Console structure used to store the state of a console render context.
Definition: console.h:77
s16
int16_t s16
16-bit signed integer
Definition: types.h:27
u32
uint32_t u32
32-bit unsigned integer
Definition: types.h:23