Homebrew Homebrew Development

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,034
Country
United States
I tried it on 3DS but it ended with an error "an exception occurred".
here is some code that will work with small ogg files. the main issue was that waveBuf was going out of scope - it needs to be valid the entire time it is being used. also, you need to set the channel volume or you wont hear anything.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <tremor/ivorbiscodec.h>
#include <tremor/ivorbisfile.h>
#include <3ds.h>
#define MUSIC_CHANNEL 1
#define BUFFER_SIZE 4096
#define STACKSIZE (4 * 1024)
typedef struct {
 float rate;
 u32 channels;
 u32 encoding;
 u32 nsamples;
 u32 size;
 u8* data;
 bool loop;
 int audiochannel;
 float mix[12];
 ndspInterpType interp;
 OggVorbis_File ovf;
} Music;
Music music;
ndspWaveBuf waveBuf;
void load() {
 memset(&music, 0, sizeof(music));
 music.mix[0] = 1.0f;
 music.mix[1] = 1.0f;
 FILE * file = fopen("example.ogg", "rb");
 if (file == 0) {
  printf("no file\n");
  while (1);
 }
 if (ov_open(file, &music.ovf, NULL, 0) < 0) {
  printf("ogg vorbis file error\n");
  while (1);
 }
 vorbis_info * vorbisInfo = ov_info(&music.ovf, -1);
 if (vorbisInfo == NULL) {
  printf("could not retrieve ogg audio stream information\n");
  while (1);
 }
 music.rate = (float)vorbisInfo->rate;
 music.channels = (u32)vorbisInfo->channels;
 music.encoding = NDSP_ENCODING_PCM16;
 music.nsamples = (u32)ov_pcm_total(&music.ovf, -1);
 music.size = music.nsamples * music.channels * 2;
 music.audiochannel = 0;
 music.interp = NDSP_INTERP_NONE;
 music.loop = false;
 if (linearSpaceFree() < music.size) {
  printf("not enough linear memory available %ld\n", music.size);
 }
 music.data = (u8 *)linearAlloc(music.size);
 if (music.data == 0) {
  printf("null\n");
  while (1);
 }
 printf("rate:%f\n", music.rate);
 printf("channels:%ld\n", music.channels);
 printf("encoding:%ld\n", music.encoding);
 printf("nsamples:%ld\n", music.nsamples);
 printf("size:%ld\n", music.size);
 int offset = 0;
 int eof = 0;
 int currentSection;
 while (!eof) {
  long ret = ov_read(&music.ovf, &music.data[offset], 4096, &currentSection);
  if (ret == 0) {
   eof = 1;
  }
  else if (ret < 0) {
   ov_clear(&music.ovf);
   linearFree(music.data);
   printf("error in the ogg vorbis stream\n");
   while (1);
  }
  else {
   offset += ret;
  }
  //printf("%ld %d\n", ret, currentSection);
 }
 printf("done\n");
 //linearFree(&music.ovf);
 ov_clear(&music.ovf);
 fclose(file);
}
int play() {
 if (music.audiochannel == -1) {
  printf("No available audio channel\n");
  return -1;
 }
 printf("music: %p\n,", music.data);
 ndspChnWaveBufClear(music.audiochannel);
 ndspChnReset(music.audiochannel);
 ndspChnInitParams(music.audiochannel);
 ndspChnSetMix(music.audiochannel, music.mix);
 ndspChnSetInterp(music.audiochannel, music.interp);
 ndspChnSetRate(music.audiochannel, music.rate);
 ndspChnSetFormat(music.audiochannel, NDSP_CHANNELS(music.channels) | NDSP_ENCODING(music.encoding));
 memset(&waveBuf, 0, sizeof(ndspWaveBuf));
 waveBuf.data_vaddr = music.data;
 waveBuf.nsamples = music.nsamples;
 waveBuf.looping = music.loop;
 waveBuf.status = NDSP_WBUF_FREE;
 DSP_FlushDataCache(music.data, music.size);
 ndspChnWaveBufAdd(music.audiochannel, &waveBuf);
// while (1);
 return 0;
}

int main(int argc, char **argv) {
 gfxInitDefault();
 consoleInit(GFX_TOP, 0);
 ndspInit();
 ndspSetOutputMode(NDSP_OUTPUT_STEREO);
 ndspSetOutputCount(1);
 load();
 play();
 while (aptMainLoop()) {
  hidScanInput();
  u32 keys = hidKeysDown();
  if (keys & KEY_START)
   break;
  gfxFlushBuffers();
  gfxSwapBuffers();
  gspWaitForVBlank();
 }
 ndspChnWaveBufClear(music.audiochannel);
 ndspExit();
 gfxExit();
 return 0;
}
 

tgaiu

Active Member
Newcomer
Joined
Sep 10, 2017
Messages
33
Trophies
0
XP
75
Country
Japan
here is some code that will work with small ogg files. the main issue was that waveBuf was going out of scope - it needs to be valid the entire time it is being used. also, you need to set the channel volume or you wont hear anything.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <tremor/ivorbiscodec.h>
#include <tremor/ivorbisfile.h>
#include <3ds.h>
#define MUSIC_CHANNEL 1
#define BUFFER_SIZE 4096
#define STACKSIZE (4 * 1024)
typedef struct {
 float rate;
 u32 channels;
 u32 encoding;
 u32 nsamples;
 u32 size;
 u8* data;
 bool loop;
 int audiochannel;
 float mix[12];
 ndspInterpType interp;
 OggVorbis_File ovf;
} Music;
Music music;
ndspWaveBuf waveBuf;
void load() {
 memset(&music, 0, sizeof(music));
 music.mix[0] = 1.0f;
 music.mix[1] = 1.0f;
 FILE * file = fopen("example.ogg", "rb");
 if (file == 0) {
  printf("no file\n");
  while (1);
 }
 if (ov_open(file, &music.ovf, NULL, 0) < 0) {
  printf("ogg vorbis file error\n");
  while (1);
 }
 vorbis_info * vorbisInfo = ov_info(&music.ovf, -1);
 if (vorbisInfo == NULL) {
  printf("could not retrieve ogg audio stream information\n");
  while (1);
 }
 music.rate = (float)vorbisInfo->rate;
 music.channels = (u32)vorbisInfo->channels;
 music.encoding = NDSP_ENCODING_PCM16;
 music.nsamples = (u32)ov_pcm_total(&music.ovf, -1);
 music.size = music.nsamples * music.channels * 2;
 music.audiochannel = 0;
 music.interp = NDSP_INTERP_NONE;
 music.loop = false;
 if (linearSpaceFree() < music.size) {
  printf("not enough linear memory available %ld\n", music.size);
 }
 music.data = (u8 *)linearAlloc(music.size);
 if (music.data == 0) {
  printf("null\n");
  while (1);
 }
 printf("rate:%f\n", music.rate);
 printf("channels:%ld\n", music.channels);
 printf("encoding:%ld\n", music.encoding);
 printf("nsamples:%ld\n", music.nsamples);
 printf("size:%ld\n", music.size);
 int offset = 0;
 int eof = 0;
 int currentSection;
 while (!eof) {
  long ret = ov_read(&music.ovf, &music.data[offset], 4096, &currentSection);
  if (ret == 0) {
   eof = 1;
  }
  else if (ret < 0) {
   ov_clear(&music.ovf);
   linearFree(music.data);
   printf("error in the ogg vorbis stream\n");
   while (1);
  }
  else {
   offset += ret;
  }
  //printf("%ld %d\n", ret, currentSection);
 }
 printf("done\n");
 //linearFree(&music.ovf);
 ov_clear(&music.ovf);
 fclose(file);
}
int play() {
 if (music.audiochannel == -1) {
  printf("No available audio channel\n");
  return -1;
 }
 printf("music: %p\n,", music.data);
 ndspChnWaveBufClear(music.audiochannel);
 ndspChnReset(music.audiochannel);
 ndspChnInitParams(music.audiochannel);
 ndspChnSetMix(music.audiochannel, music.mix);
 ndspChnSetInterp(music.audiochannel, music.interp);
 ndspChnSetRate(music.audiochannel, music.rate);
 ndspChnSetFormat(music.audiochannel, NDSP_CHANNELS(music.channels) | NDSP_ENCODING(music.encoding));
 memset(&waveBuf, 0, sizeof(ndspWaveBuf));
 waveBuf.data_vaddr = music.data;
 waveBuf.nsamples = music.nsamples;
 waveBuf.looping = music.loop;
 waveBuf.status = NDSP_WBUF_FREE;
 DSP_FlushDataCache(music.data, music.size);
 ndspChnWaveBufAdd(music.audiochannel, &waveBuf);
// while (1);
 return 0;
}

int main(int argc, char **argv) {
 gfxInitDefault();
 consoleInit(GFX_TOP, 0);
 ndspInit();
 ndspSetOutputMode(NDSP_OUTPUT_STEREO);
 ndspSetOutputCount(1);
 load();
 play();
 while (aptMainLoop()) {
  hidScanInput();
  u32 keys = hidKeysDown();
  if (keys & KEY_START)
   break;
  gfxFlushBuffers();
  gfxSwapBuffers();
  gspWaitForVBlank();
 }
 ndspChnWaveBufClear(music.audiochannel);
 ndspExit();
 gfxExit();
 return 0;
}
I'm really thankful to you! I will refer to your code.
 

Togetoge

Active Member
Newcomer
Joined
Sep 18, 2017
Messages
32
Trophies
0
Age
124
Website
github.com
XP
301
Country
Japan
I played music files using ndsp but playback finished faster than playing on Windows.
Is there a way to prevent this?

Sorry, this problem has already been solved.
 
Last edited by Togetoge,

MaiconErick

Well-Known Member
Member
Joined
Jan 4, 2016
Messages
140
Trophies
0
Age
28
XP
373
Country
Brazil
How can I search for all instaled titles and store their title IDs in a list?
I'm playing and learning with the DevKit's examples, but didn't find anything related.
Help :)
 

MaiconErick

Well-Known Member
Member
Joined
Jan 4, 2016
Messages
140
Trophies
0
Age
28
XP
373
Country
Brazil
You could look at the source for FBI and see how it does it.
That's what I'm doing, I'm starting with 3DSident's "Installed title count", to have an idea of how it works first.
It's really the hard way, I don't know what they're doing, I'm just trying to follow along haha

I can't even find where the method(s) for listing the titles are in fbi source.
 
Last edited by MaiconErick,

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,034
Country
United States

MaiconErick

Well-Known Member
Member
Joined
Jan 4, 2016
Messages
140
Trophies
0
Age
28
XP
373
Country
Brazil
I got my TitleID value stored in a u64 titleID[1] in decimal.
I need help on how to use it on this function:
APT_PrepareToDoApplicationJump(0, 0x000XLL, 0),
where X stands for the titleID value in hexadecimal.
Spent some hours already trying to look up how to do this using C, so I decided to ask for help here.


the titleID is 16 (decimal) numbers long.
the X value I need, should be 13 (hex) numbers long.

EDIT: Figured it out.
 
Last edited by MaiconErick,

tgaiu

Active Member
Newcomer
Joined
Sep 10, 2017
Messages
33
Trophies
0
XP
75
Country
Japan
I attempted to play the stream of ogg files, but the playback speed got a little faster.
Please help me.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <tremor/ivorbiscodec.h>
#include <tremor/ivorbisfile.h>
#include <3ds.h>

#define BUFF_SIZE 8 * 4096
typedef struct {
    float rate;
    u32 channels;
    u32 encoding;
    u32 nsamples;
    u32 size;
    char* data1;
    char* data2;
    bool loop;
    int audiochannel;
    float mix[12];
    ndspInterpType interp;
    OggVorbis_File ovf;
} Music;
Music music;
ndspWaveBuf waveBuf[2];

uint64_t fillVorbisBuffer(OggVorbis_File ovf, char* buffer) {
    uint64_t samplesRead = 0;
    int samplesToRead = BUFF_SIZE;

    while (samplesToRead > 0) {

        static int current_section;
        int samplesJustRead =
            ov_read(&ovf,
                buffer,
                samplesToRead > 4096 ? 4096 : samplesToRead,
                &current_section);
        if (samplesJustRead < 0)
            return samplesJustRead;
        else if (samplesJustRead == 0){
            break;
        }
        samplesRead += samplesJustRead;
        samplesToRead -= samplesJustRead;
        buffer += samplesJustRead;
    }
    return samplesRead / sizeof(int16_t);
}


int load() {
    memset(&music, 0, sizeof(music));
    music.mix[0] = 1.0f;
    music.mix[1] = 1.0f;
    FILE * file = fopen("example.ogg", "rb");
    if (file == 0) {
        printf("no file\n");
        while (1);
    }
    if (ov_open(file, &music.ovf, NULL, 0) < 0) {
        printf("ogg vorbis file error\n");
        while (1);
    }
    vorbis_info * vorbisInfo = ov_info(&music.ovf, -1);
    if (vorbisInfo == NULL) {
        printf("could not retrieve ogg audio stream information\n");
        while (1);
    }
    music.rate = (float)vorbisInfo->rate;
    music.channels = (u32)vorbisInfo->channels;
    music.encoding = NDSP_ENCODING_PCM16;
    music.nsamples = (u32)ov_pcm_total(&music.ovf, -1);
    music.size = music.nsamples * music.channels * 2;
    music.audiochannel = 0;
    music.interp = NDSP_INTERP_NONE;
    music.loop = false;
    if (linearSpaceFree() < music.size) {
        printf("not enough linear memory available %ld\n", music.size);
    }
    music.data1 = (char *)linearAlloc(BUFF_SIZE * sizeof(int16_t));
    music.data2 = (char *)linearAlloc(BUFF_SIZE * sizeof(int16_t));
    printf("rate:%f\n", music.rate);
    printf("channels:%ld\n", music.channels);
    printf("encoding:%ld\n", music.encoding);
    printf("nsamples:%ld\n", music.nsamples);
    printf("size:%ld\n", music.size);
    //fclose(file);
    if (music.audiochannel == -1) {
        printf("No available audio channel\n");
        return -1;
    }
    ndspChnWaveBufClear(music.audiochannel);
    ndspChnReset(music.audiochannel);
    ndspChnInitParams(music.audiochannel);
    ndspChnSetMix(music.audiochannel, music.mix);
    ndspChnSetInterp(music.audiochannel, music.interp);
    ndspChnSetRate(music.audiochannel, music.rate);
    ndspChnSetFormat(music.audiochannel, NDSP_CHANNELS(music.channels) | NDSP_ENCODING(music.encoding));
    memset(&waveBuf, 0, sizeof(ndspWaveBuf));
    waveBuf[0].data_vaddr = &music.data1[0];
    waveBuf[0].nsamples = fillVorbisBuffer(music.ovf, &music.data1[0]) / music.channels;
    waveBuf[0].looping = music.loop;
    waveBuf[1].data_vaddr = &music.data2[0];
    waveBuf[1].nsamples = fillVorbisBuffer(music.ovf, &music.data1[0]) / music.channels;
    waveBuf[1].looping = music.loop;
    return 0;
}

int main(int argc, char **argv) {
    gfxInitDefault();
    consoleInit(GFX_TOP, 0);
    ndspInit();
    ndspSetOutputMode(NDSP_OUTPUT_STEREO);
    ndspSetOutputCount(1);
    load();
  
    ndspChnWaveBufAdd(0, &waveBuf[0]);
    ndspChnWaveBufAdd(0, &waveBuf[1]);

    while (aptMainLoop()) {
        hidScanInput();
        u32 keys = hidKeysDown();
        if (keys & KEY_START)
            break;

        if (waveBuf[0].status == NDSP_WBUF_DONE){
            size_t read = fillVorbisBuffer(music.ovf, &music.data1[0]);

            if (read <= 0){
                continue;
            }
            else if (read < BUFF_SIZE)
                waveBuf[0].nsamples = read / music.channels;

            ndspChnWaveBufAdd(music.audiochannel, &waveBuf[0]);
        }

        if (waveBuf[1].status == NDSP_WBUF_DONE){
            size_t read = fillVorbisBuffer(music.ovf, &music.data2[0]);

            if (read <= 0){
                continue;
            }
            else if (read < BUFF_SIZE)
                waveBuf[1].nsamples = read / music.channels;

            ndspChnWaveBufAdd(music.audiochannel, &waveBuf[1]);
        }
        DSP_FlushDataCache(music.data1, BUFF_SIZE * sizeof(int16_t));
        DSP_FlushDataCache(music.data2, BUFF_SIZE * sizeof(int16_t));
        //printf("%d:%d\n", waveBuf[0].status, waveBuf[1].status);
        gfxFlushBuffers();
        gfxSwapBuffers();
        gspWaitForVBlank();
    }
    ndspChnWaveBufClear(music.audiochannel);
    ndspExit();
    gfxExit();
    return 0;
}
 
Last edited by tgaiu,

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • Psionic Roshambo @ Psionic Roshambo:
    Now that they decided to add Tiger handheld and fruit machines.... Newer sets are worthless
  • Psionic Roshambo @ Psionic Roshambo:
    Because who doesn't want to emulate Halo LCD by Tiger when the machine needed to emulate it... Could just play Halo....
  • K3Nv2 @ K3Nv2:
    Batocera has some tiger games
  • Psionic Roshambo @ Psionic Roshambo:
    I don't have them on mine Ken lol
  • K3Nv2 @ K3Nv2:
    Waste of the 128kb they take
    +1
  • Psionic Roshambo @ Psionic Roshambo:
    Tiger handhelds are good for one thing.... Occupying space in a landfill
  • K3Nv2 @ K3Nv2:
    They make good burning plastic
  • BigOnYa @ BigOnYa:
    Makes me wonder if the Pi5 can play PS2? If there's even a core for it yet.
  • K3Nv2 @ K3Nv2:
    Pi5 should be able to do ps2
  • Psionic Roshambo @ Psionic Roshambo:
    Try Dragon Quest VIII it ran perfectly on a core 2 Duo I had
  • Psionic Roshambo @ Psionic Roshambo:
    Easiest game to run I found
  • K3Nv2 @ K3Nv2:
    Ps2 emulation is cake compared to 3 years ago
  • Psionic Roshambo @ Psionic Roshambo:
    Hardest is probably Gran Turismo 4
  • Psionic Roshambo @ Psionic Roshambo:
    It's much better now yes but Gran Turismo 4 is still the hardest one to emulate that I have in my collection
  • Psionic Roshambo @ Psionic Roshambo:
    Runs perfectly fine but it's as if I can feel it always on the boarder line of dropping a frame lol
  • BigOnYa @ BigOnYa:
    I ordered a spin ball couple days ago to add to my arcade cabinet, will be nice for games like golden tee, or bowling
  • Psionic Roshambo @ Psionic Roshambo:
    I always wanted a controller for like Ikari Warriors, Time Soldiers, Heavy Barrel, Forgotten Worlds games like those
    +1
  • Psionic Roshambo @ Psionic Roshambo:
    Not even sure what to call that controller
  • Xdqwerty @ Xdqwerty:
    an online friend I've known since 2021 left me :( bc my attitude is "cutty"
  • Psionic Roshambo @ Psionic Roshambo:
    Sylvester Stallone should have played Kyle Reese lol Arnold still as the Terminator
  • BakerMan @ BakerMan:
    TF DOES "CUTTY" EVEN MEAN?
  • Xdqwerty @ Xdqwerty:
    @BakerMan, he is peruvian so it's probably an idiom
  • BigOnYa @ BigOnYa:
    I thought Cutty was a west coast rapper
  • K3Nv2 @ K3Nv2:
    Cutter
    K3Nv2 @ K3Nv2: Cutter