使用3DS音频播放正弦波

时间:2018-07-04 20:03:02

标签: c++ audio 3ds devkitpro

嗨,我只是进入音频编程领域,我想从3DS开始做一个基本的便携式合成器。 devkitpro附带了一些示例代码,显示了从扬声器播放的正弦波的简单实现。我一直在试图理解它,并且它一直在取得一些成功。问题在于代码的文档编写不充分,仅调用了一些函数,我仅从它们的命名就无法理解。我在网上看过,但是,a,我什么也没找到。我只是希望有人可以将我的资源指向正确的方向,该资源可以解释3DS音频编程,或者有人可以逐行解释代码。

这是代码(所有注释均由我提供,以帮助我理解它,我不知道它们是否正确,但我认为它们是正确的):

#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;//allows dest to access audio buffer
//fills audio buffer and adds a sample to it for each i
    for (int i=0; i<size; i++) {

    //divided by the sample rate to scale the wave to how time is
    //freq*2PI*(offset+i) results in the angle at that time of the wave and INT16_MAX is equivalent to the amplitude
        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) {
//----------------------------------------------------------------------------
//initialises wave buffer
    PrintConsole topScreen;
    ndspWaveBuf waveBuf[2];
//initialises the graphics for the 3ds
    gfxInitDefault();

//initialises screen

    consoleInit(GFX_TOP, &topScreen);

    consoleSelect(&topScreen);

    printf("libctru streaming audio\n");
//sets aside memory for the audio buffer to be stored
    u32 *audioBuffer = (u32*)linearAlloc(SAMPLESPERBUF*BYTESPERSAMPLE*2);
//acts as a toggle flag
    bool fillBlock = false;
//initialises audio
    ndspInit();

//initialises speakers to stereo output and sets the sample rate
    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));//sets all elements of the array to zero
    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));//clears 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;//variable to hold how far into the wave has run

    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;
        }
//checks if audio buffer has been emptied if it has, it refills it
        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;
}

感谢所有回答此问题的人,因为我想避免盲目使用代码。

0 个答案:

没有答案