Tuesday, July 28, 2020

Basics on the code PART 11

In this entry we will see how the vita generates sounds. This could be useful when we want warnings or similar things to have sound.

Note: The VM we were using was setup without enough space and "broke", so we will be using another one with ubuntu 20 from now on. The reason of the firmware change is explained in this entry. If your machine have enough space, it is not required to change it.

To help us to understand the functions of this sample, we have to use the vitasdk documentation, for this specific sample we will use the audio section. Also, the the audioout header section.


SAMPLE "audio"

audio: Simple audio wave generator.


#include <stdint.h>
#include <math.h>

#include <psp2/ctrl.h>
#include <psp2/audioout.h>
#include <psp2/kernel/processmgr.h>

#include "debugScreen.h"

// functions to control the frequency changes
#define countof(A) sizeof(A)/sizeof(*A)
#define MIN(A,B) ((A)<(B)?(A):(B))
#define MAX(A,B) ((A)>(B)?(A):(B))

#define printf psvDebugScreenPrintf

// frequency function and its variables based on the button input to change accordingly
double gen_sqr(double p){return p>.5?-1.:1.;}
double gen_tri(double p){return p*2;}
double gen_nul(double p){return 0.;}
double gen_sin(double p){return sin(2*M_PI*p);}

typedef double (*wav_gen)(double);

// audio wave generetator function
void wave_set(int16_t*buffer, size_t size,  wav_gen generator){
    for (size_t smpl = 0; smpl < size; ++smpl)
        buffer[smpl] = 0x7FFF*generator((float)smpl/(float)size);
}

// main program

int main(void) {
    psvDebugScreenInit();


// audio and wave variables during the execution
    int freqs[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000};
    int size = 256;
    int freq = 8;
    int mode = SCE_AUDIO_OUT_MODE_MONO;
    int vol = SCE_AUDIO_VOLUME_0DB;


// current running wave variable
    int port = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_BGM, size, freqs[freq], mode);
    sceAudioOutSetVolume(port, SCE_AUDIO_VOLUME_FLAG_L_CH |SCE_AUDIO_VOLUME_FLAG_R_CH, (int[]){vol,vol});


// wave data and its control functions based on the input button in execution time
    int16_t wave_buf[SCE_AUDIO_MAX_LEN]={0};
    wav_gen gen=gen_nul;
    SceCtrlData ctrl_peek, ctrl_press;
    do{
        ctrl_press = ctrl_peek;
        sceCtrlPeekBufferPositive(0, &ctrl_peek, 1);
        ctrl_press.buttons = ctrl_peek.buttons & ~ctrl_press.buttons;

        if(ctrl_press.buttons == SCE_CTRL_CIRCLE)
            gen=gen_sin;
        if(ctrl_press.buttons == SCE_CTRL_SQUARE)
            gen=gen_sqr;
        if(ctrl_press.buttons == SCE_CTRL_TRIANGLE)
            gen=gen_tri;
        if(ctrl_press.buttons == SCE_CTRL_CROSS)
            gen=gen_nul;
        if(ctrl_press.buttons & (SCE_CTRL_CROSS|SCE_CTRL_TRIANGLE|SCE_CTRL_SQUARE|SCE_CTRL_CIRCLE))
            wave_set(wave_buf,size,gen);
          
        if(ctrl_press.buttons == SCE_CTRL_RIGHT)
            freq = MIN(countof(freqs)-1, freq+1);
        if(ctrl_press.buttons == SCE_CTRL_LEFT)
            freq = MAX(0, freq-1);
        if(ctrl_press.buttons == SCE_CTRL_RTRIGGER)
            size = MIN(SCE_AUDIO_MAX_LEN,size+1000);
        if(ctrl_press.buttons == SCE_CTRL_LTRIGGER)
            size = MAX(SCE_AUDIO_MIN_LEN,size-1000);
        if(ctrl_press.buttons & (SCE_CTRL_RIGHT|SCE_CTRL_LEFT|SCE_CTRL_LTRIGGER|SCE_CTRL_RTRIGGER)){
            sceAudioOutSetConfig(port, size, freqs[freq], mode);
            wave_set(wave_buf,size,gen);
        }

        if(ctrl_press.buttons == SCE_CTRL_UP)
            vol = MIN(vol+1024,SCE_AUDIO_VOLUME_0DB);
        if(ctrl_press.buttons == SCE_CTRL_DOWN)
            vol = MAX(vol-1024,0);
        if(ctrl_press.buttons & (SCE_CTRL_UP|SCE_CTRL_DOWN))
            sceAudioOutSetVolume(port, SCE_AUDIO_VOLUME_FLAG_L_CH |SCE_AUDIO_VOLUME_FLAG_R_CH, (int[]){vol,vol});

        sceAudioOutOutput(port, wave_buf);
        printf("freq:%-5i size:%-5i vol:%-5i  wave:{%+6i..%+6i..%6i..%+6i }\r",
                freqs[freq], size, vol, wave_buf[0*size/4], wave_buf[1*size/4], wave_buf[2*size/4], wave_buf[3*size/4]);//\e[H
    }while(ctrl_press.buttons != SCE_CTRL_START); // // sample loop for testing until start button is pressed


    sceAudioOutReleasePort(port);
    sceKernelExitProcess(0);
    return 0;
}


-----------

Some screenshots from the sample running on the vita:

Basic screen before any input

Wave stopped (after being running)

One posible running wave

And that's all for this sample.

No comments:

Post a Comment