Homebrew CSND - playing sound data built into the binary

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,074
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!
 

elhobbs

Well-Known Member
Member
Joined
Jul 28, 2008
Messages
1,044
Trophies
1
XP
3,034
Country
United States
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.
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,074
Country
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...)
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,074
Country
@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);
}
 

BurningDesire

Well-Known Member
Member
Joined
Jan 27, 2015
Messages
4,999
Trophies
1
Location
Behind a screen reading news
XP
4,885
Country
United States
@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:
 

BurningDesire

Well-Known Member
Member
Joined
Jan 27, 2015
Messages
4,999
Trophies
1
Location
Behind a screen reading news
XP
4,885
Country
United States
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
 

MasterFeizz

Well-Known Member
Member
Joined
Oct 15, 2015
Messages
1,098
Trophies
1
Age
29
XP
3,710
Country
United States
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?
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,074
Country
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

MasterFeizz

Well-Known Member
Member
Joined
Oct 15, 2015
Messages
1,098
Trophies
1
Age
29
XP
3,710
Country
United States
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

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,074
Country
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

TheCruel

Developer
Banned
Joined
Dec 6, 2013
Messages
1,350
Trophies
2
XP
3,131
Country
United States
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.
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
40
Location
Kongo Jungle
XP
5,074
Country
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

General chit-chat
Help Users
    K3Nv2 @ K3Nv2: https://www.phonearena.com/phones/compare/Samsung-Galaxy-S22+,Google-Pixel-8a/phones/11762,12219...