Homebrew Development

Discussion in '3DS - Homebrew Development and Emulators' started by aliak11, Jan 16, 2014.

  1. tgaiu

    tgaiu Member

    Newcomer
    33
    3
    Sep 10, 2017
    Japan
    I made those improvements but got errors.
    Code:
    [HW.Memory <Error> core\memory.cpp:GetPointer:283: unknown GetPointer @ 0x00000000
    [Audio.DSP <Warning> audio_core\hle\source.cpp:DequeueBuffer:312: source_id=0 buffer_id=20 length=0: Invalid physical address 0x00000000
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #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;
    
    void load() {
    	FILE * file = fopen("example.ogg", "rb");
    	if (ov_open(file, &music.ovf, NULL, 0) < 0) {
    		printf("ogg vorbis file error\n");
    	}
    	vorbis_info * vorbisInfo = ov_info(&music.ovf, -1);
    	if (vorbisInfo == NULL) {
    		printf("could not retrieve ogg audio stream information\n");
    	}
    	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.loop = false;
    	if (linearSpaceFree() < music.size) {
    		printf("not enough linear memory available\n");
    	music.data = static_cast<u8*>(linearAlloc(music.size));
    
    	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");
    		}
    		else {
    			offset += ret;
    		}
    	}
    	linearFree(&music.ovf);
    	ov_clear(&music.ovf);
    	fclose(file);
    }
    
    int play() {
    	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));
    
    	ndspWaveBuf waveBuf;
    	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);
    	return 0;
    }
    
    
    int main() {
    	gfxInitDefault();
    	consoleInit(GFX_TOP, nullptr);
    
    	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);
    	gfxExit();
    	ndspExit();
    	return 0;
    }
     
  2. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    818
    302
    Jul 28, 2008
    United States
    Check if linearAlloc succeeded?
    Why are you calling linearFree in the load function - on non “linear” region memory(music.ovf)?
     
  3. tgaiu

    tgaiu Member

    Newcomer
    33
    3
    Sep 10, 2017
    Japan
    I made a mistake in placing linearFree.
    linearAlloc seemed to be successful.
    It seems that gspWaitForVBlank () is causing problems, but is it OK to delete this?
     
  4. cracker

    cracker Nyah!

    Member
    3,211
    479
    Aug 24, 2005
    United States
    If you don't mind screen tearing.
     
  5. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    818
    302
    Jul 28, 2008
    United States
    If gspWaitForVBlank is having problems - then something else is causing it.
     
  6. niBBasian

    niBBasian Newbie

    Newcomer
    7
    1
    Nov 27, 2017
    Singapore
    guys i know this sounds silly but i am new to the modding scene and also to gba temp . BUT I DONT KNOW HOW TO POST A FU#%ING question!!!!!!!!!!!!!!!HOW DO U POST ON GBATEMP NET!!!!!!!!!!!!!!!!!!
     
  7. NatsumiX

    NatsumiX Advanced Member

    Newcomer
    64
    53
    Oct 9, 2017
    United States
    [​IMG]
     
    B_E_P_I_S_M_A_N and CrimsonMaple like this.
  8. tgaiu

    tgaiu Member

    Newcomer
    33
    3
    Sep 10, 2017
    Japan
    I tried a variety of hands, but I get a similar error.
    Please let me know if you know the solution.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <tremor/ivorbiscodec.h>
    #include <tremor/ivorbisfile.h>
    #include <3ds.h>
    
    typedef struct {
    	float rate;
    	u32 channels;
    	u32 encoding;
    	u32 nsamples;
    	u32 size;
    	char* data;
    	bool loop;
    	int audiochannel;
    	float mix[12];
    	ndspInterpType interp;
    	OggVorbis_File ovf;
    } Music;
    Music music;
    
    void load() {
    	FILE * file = fopen("test.ogg", "rb");
    	if (ov_open(file, &music.ovf, NULL, 0) < 0) {
    		printf("ogg vorbis file error\n");
    	}
    	vorbis_info * vorbisInfo = ov_info(&music.ovf, -1);
    	if (vorbisInfo == NULL) {
    		printf("could not retrieve ogg audio stream information\n");
    	}
    	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.loop = false;
    	music.interp = NDSP_INTERP_NONE;
    	if (linearSpaceFree() < music.size) {
    		printf("not enough linear memory available\n");
    	}
    	music.data = static_cast<char*>(linearAlloc(music.size));
    	if (!music.data){
    		fclose(file);
    	}
    	printf("buffersize:%d\n", linearGetSize(music.data));
    	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);
    
    	// Decoding loop
    	int offset = 0;
    	int eof = 0;
    	int currentSection = 0;
    	int readSize = 0;
    	int comSize = 0;
    	char* tmpBuffer = static_cast<char*>(linearAlloc(music.size));
    	while (1) {
    		readSize = ov_read(&music.ovf, (char*)tmpBuffer, 4096, &currentSection);
    		if (readSize == 0) break; //EOF
    		memcpy(music.data + comSize, tmpBuffer, readSize);
    		comSize += readSize;
    	}
    	fclose(file);
    }
    
    int play() {
    	if (music.audiochannel == -1) {
    		printf("No available audio channel\n");
    		return -1;
    	}
    	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));
    	
    	ndspWaveBuf waveBuf;
    	memset(&waveBuf, 0, sizeof(ndspWaveBuf));
    	waveBuf.data_vaddr = (const void*)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);
    	return 0;
    }
    
    
    int main() {
    	gfxInitDefault();
    	consoleInit(GFX_TOP, nullptr);
    
    	ndspInit();
    	ndspSetOutputMode(NDSP_OUTPUT_STEREO);
    	ndspSetOutputCount(1);
    
    	load();
    	play();
    	while (aptMainLoop()) {
    		hidScanInput();
    		u32 keys = hidKeysDown();
    		if (keys & KEY_START)
    			break;
    		gfxFlushBuffers();
    		gfxSwapBuffers();
    		gspWaitForVBlank();
    	}
    	linearFree(&music.ovf);
    	ov_clear(&music.ovf);
    	ndspChnWaveBufClear(music.audiochannel);
    	gfxExit();
    	ndspExit();
    	return 0;
    }
     
  9. cracker

    cracker Nyah!

    Member
    3,211
    479
    Aug 24, 2005
    United States
    That's not necessarily a problem with your code. Even legit games have that error in Citra. You will need to use the real hardware to test it.
     
  10. tgaiu

    tgaiu Member

    Newcomer
    33
    3
    Sep 10, 2017
    Japan
    I tried it on 3DS but it ended with an error "an exception occurred".
     
  11. MyLegGuy

    MyLegGuy Moron

    Member
    562
    358
    Nov 26, 2014
    United States
    Just a random idea, make sure you're loading a small OGG file because you're loading it all into memory at once.
     
  12. tgaiu

    tgaiu Member

    Newcomer
    33
    3
    Sep 10, 2017
    Japan
    Are you talking about streaming play?
    Should I try it?
     
  13. MyLegGuy

    MyLegGuy Moron

    Member
    562
    358
    Nov 26, 2014
    United States
    First, try loading a small file. An OGG file that is around 3 or 4 seconds long is short enough. Streaming is a little bit harder to do, so you should just try to get small files working first.
    If you can get that working, then program streaming for big file.

    Also, here's some code I wrote with OGG and WAV streaming using libvorbisfile for OGG and dr_wav.h for WAV that you can look at as an example.
    https://github.com/MyLegGuy/libGeneralGood/blob/master/src/3dsSound.h
     
    Last edited by MyLegGuy, Dec 15, 2017
  14. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    818
    302
    Jul 28, 2008
    United States
    Also make sure you run the dsp dump utility on hardware. You will need to copy the file from hardware to the sd card folder for Citra - make sure you use the same path.
     
    MyLegGuy likes this.
  15. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    818
    302
    Jul 28, 2008
    United States
    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;
    }
    
     
  16. tgaiu

    tgaiu Member

    Newcomer
    33
    3
    Sep 10, 2017
    Japan
    I'm really thankful to you! I will refer to your code.
     
  17. MyLegGuy

    MyLegGuy Moron

    Member
    562
    358
    Nov 26, 2014
    United States
    Can I just call exit(0) to exit my CIA homebrew, or do I actually have to clean up everything? (sdmcExit(), fsExit(), romfsExit(), etc.)
     
  18. jockep

    jockep GBAtemp Regular

    Member
    170
    59
    Apr 12, 2017
    Pretty sure not doing that will leave resources in memory which is bad.
     
    Joel16 likes this.
  19. Togetoge

    Togetoge Member

    Newcomer
    12
    1
    Sep 18, 2017
    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, Dec 21, 2017
  20. shado_eagle
    This message by shado_eagle has been removed from public view by porkiewpyne, Dec 22, 2017, Reason: Shitpost.
    Dec 21, 2017
  21. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    818
    302
    Jul 28, 2008
    United States
    You need to exit everything you initialize yourself.