Homebrew CSND - playing sound data built into the binary

  • Thread starter Thread starter mashers
  • Start date Start date
  • Views Views 2,174
  • Replies Replies 19

mashers

Stubborn ape
Member
Joined
Jun 10, 2015
Messages
3,837
Reaction score
5,181
Trophies
0
Age
42
Location
Kongo Jungle
XP
5,129
Country
The sound playing code in Gridlauncher loads a WAV file from the SD card and plays it. I now want to play sound data which has been included in the 3dsx binary itself but I can't get it working.

My WAV file already has a .bin extension and it plays in Gridlauncher as a theme sound loaded from SD. I place this in the data directory, included its header, and tried to call cSndPlaySound() passing this buffer as the data parameter. The problem is that no sound actually plays.

I'm wondering whether the compiler is doing something to the .bin (really .wav) file when it links it with the binary rather than including it as-is. Does anyone have any ideas about this?

Thanks in advance!
 
The sound playing code in Gridlauncher loads a WAV file from the SD card and plays it. I now want to play sound data which has been included in the 3dsx binary itself but I can't get it working.

My WAV file already has a .bin extension and it plays in Gridlauncher as a theme sound loaded from SD. I place this in the data directory, included its header, and tried to call cSndPlaySound() passing this buffer as the data parameter. The problem is that no sound actually plays.

I'm wondering whether the compiler is doing something to the .bin (really .wav) file when it links it with the binary rather than including it as-is. Does anyone have any ideas about this?

Thanks in advance!
The sound data must be in the linear address range. You will need to copy the data there and pass that address to csnd instead.
 
The sound data must be in the linear address range. You will need to copy the data there and pass that address to csnd instead.
Thanks buddy! So would that involve mallocing some memory at runtime and then memcpying from the data included in the binary to the malloced space? (in the gym so can't experiment...)
 
Thanks buddy! So would that involve mallocing some memory at runtime and then memcpying from the data included in the binary to the malloced space? (in the gym so can't experiment...)
linearAlloc rather than malloc, but essentially yes.
 
Awww man, nerd talk i can't be a part of... Which language should i start learning guys....
 
Awww man, nerd talk i can't be a part of... Which language should i start learning guys....
I would suggest C IMO since I guess it is more commonly used through the homebrew section. However, if you want to learn a noob friendly language I would start with @Rinnegatamante's lua for 3ds
 
linearAlloc rather than malloc, but essentially yes.
Thanks mate. In the end, it actually worked using the data included in the binary if I cast it explicitly as (void*). I didn't need to linearAlloc and memcpy in the end! Thank you anyway for your suggestions :)
 
@elhobbs
Actually, I have now switched to using your linearAlloc method. This works better as I can leave off the first 48 bytes to remove the playback pop. Here's the final solution:

Code:
void * loadSound(void * source, int size) {
    size -= 0x48;
    void * sound = linearAlloc(size);
    memcpy(sound, source+0x48, size);
    return sound;
}

void audioStop(int channel) {
    csndExecCmds(true);
    CSND_SetPlayState(channel, 0);
    csndExecCmds(true);
}



void audioPlay(void * audio, int channel, u32 size) {
    audioStop(channel);
    csndPlaySound(channel, SOUND_FORMAT_16BIT, 44100, 1, 0, audio, audio, size);
}

int main() {
    // ...

    //pipe_bin is the audio data included in the 3dsx
    //pipe_bin_size is the size of the data
    void * pipeSound = loadSound((void*)pipe_bin, pipe_bin_size);

    // ...

    // Yeah I should probably put the data and size into a struct to make this cleaner, but it's only a one off...
    audioPlay(pipeSound, 8, pipe_bin_size);

    // ...

    linearFree(pipeSound);
}
 
@elhobbs
Actually, I have now switched to using your linearAlloc method. This works better as I can leave off the first 48 bytes to remove the playback pop. Here's the final solution:

Code:
void * loadSound(void * source, int size) {
    size -= 0x48;
    void * sound = linearAlloc(size);
    memcpy(sound, source+0x48, size);
    return sound;
}

void audioStop(int channel) {
    csndExecCmds(true);
    CSND_SetPlayState(channel, 0);
    csndExecCmds(true);
}



void audioPlay(void * audio, int channel, u32 size) {
    audioStop(channel);
    csndPlaySound(channel, SOUND_FORMAT_16BIT, 44100, 1, 0, audio, audio, size);
}

int main() {
    // ...

    //pipe_bin is the audio data included in the 3dsx
    //pipe_bin_size is the size of the data
    void * pipeSound = loadSound((void*)pipe_bin, pipe_bin_size);

    // ...

    // Yeah I should probably put the data and size into a struct to make this cleaner, but it's only a one off...
    audioPlay(pipeSound, 8, pipe_bin_size);

    // ...

    linearFree(pipeSound);
}
Why does coding look so simple then when you do it your in hell :cry:
 
Coding IS simple. It's the API that's hard. Once you know which API calls to make, working out the actual code is easy ;)
My main problem is learning what do to with the .h files and how to implement voids and how to make the code prettier. I can do stuff it just looks ugly as fuck. I started porting qben to mac with Glew and glfw for a learning experience. I don't understand .h files ;( or anything that isn't in the main haha
 
My main problem is learning what do to with the .h files and how to implement voids and how to make the code prettier. I can do stuff it just looks ugly as fuck. I started porting qben to mac with Glew and glfw for a learning experience. I don't understand .h files ;( or anything that isn't in the main haha
Isn't qBen's code already platform independent?
 
My main problem is learning what do to with the .h files and how to implement voids and how to make the code prettier. I can do stuff it just looks ugly as fuck. I started porting qben to mac with Glew and glfw for a learning experience. I don't understand .h files ;( or anything that isn't in the main haha
The header (.h) file is like an index. It tells other implementation (.c, .cpp, ...) files what is contained inside the implementation file which does along with the header. So if you define a function within a .c file and want other .c files to be able to access it, you add a definition for the function into its .h file :)
 
  • Like
Reactions: BurningDesire
My main problem is learning what do to with the .h files and how to implement voids and how to make the code prettier. I can do stuff it just looks ugly as fuck. I started porting qben to mac with Glew and glfw for a learning experience. I don't understand .h files ;( or anything that isn't in the main haha

A void is an empty data type and a void pointer is a generic pointer, so you don't implement voids, you implement functions.
 
  • Like
Reactions: BurningDesire
A void is an empty data type and a void pointer is a generic pointer, so you don't implement voids, you implement functions.
I think he meant functions when he wrote voids.

@BurningDesire
The 'void' before a function declaration means the function doesn't return anything. You can put any other datatype here to specify what type of data the function returns. For example:

Code:
void func1() {
    //Do something
    //Return nothing
}

int func2() {
    int r = 42;
    return r;
}

char * func3() {
    char * r = "Hello world";
    return r;
}

bool func4() {
    bool r = true;
    return r;
}
 
  • Like
Reactions: BurningDesire
If you parse the 3dsx header, you can find the RomFS offset, then you can play a sort of banner audio provided by the 3dsx files. Can just tell devs to use some sort of standard filename like "banner.wav" and you can fallback on a "banner.wav" in the game dir if there is no RomFS present. Just an idea, since you're implementing audio.
 
If you parse the 3dsx header, you can find the RomFS offset, then you can play a sort of banner audio provided by the 3dsx files. Can just tell devs to use some sort of standard filename like "banner.wav" and you can fallback on a "banner.wav" in the game dir if there is no RomFS present. Just an idea, since you're implementing audio.
Thanks, but that's not really relevant to the situation I'm in. I'm just including audio files in the 3dsx to be played by the software so they don't have to be bundled as external files.
 

Site & Scene News

Popular threads in this forum