Add Initial Music Playback, because I just feel like doing it. 😛

Put `Music.wav` to `sdmc:/3ds/Universal-Updater/`. **Warning**: The Wav File should not be larger than 13 / 14 MB, otherwise it will crash.
This commit is contained in:
VoltZ
2019-11-17 22:34:04 +01:00
parent 2921ce0b2d
commit 5f5669678d
3 changed files with 195 additions and 1 deletions
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <3ds.h>
#include <string>
class sound
{
public:
sound(const std::string& path, int channel = 1, bool toloop = true);
~sound();
void play();
void stop();
private:
u32 dataSize;
ndspWaveBuf waveBuf;
u8* data = NULL;
int chnl;
};
+43 -1
View File
@@ -32,6 +32,7 @@
#include "screens/screenCommon.hpp"
#include "utils/config.hpp"
#include "utils/sound.h"
#include "utils/structs.hpp"
#include <3ds.h>
@@ -39,8 +40,11 @@
#include <unistd.h>
bool exiting = false;
bool dspFound = false;
touchPosition touch;
sound *bgm = NULL;
bool songIsFound = false;
// If button Position pressed -> Do something.
bool touching(touchPosition touch, Structs::ButtonPos button) {
@@ -50,6 +54,28 @@ bool touching(touchPosition touch, Structs::ButtonPos button) {
return false;
}
void loadSoundEffects(void) {
if (dspFound == true) {
if( access( "sdmc:/3ds/Universal-Updater/Music.wav", F_OK ) != -1 ) {
bgm = new sound("sdmc:/3ds/Universal-Updater/Music.wav", 1, true);
songIsFound = true;
}
}
}
void playMusic(void) {
if (songIsFound == true) {
bgm->play();
}
}
void stopMusic(void) {
if (songIsFound == true) {
bgm->stop();
}
}
int main()
{
gfxInitDefault();
@@ -72,6 +98,14 @@ int main()
Gui::setScreen(std::make_unique<MainMenu>());
osSetSpeedupEnable(true); // Enable speed-up for New 3DS users
if( access( "sdmc:/3ds/dspfirm.cdc", F_OK ) != -1 ) {
ndspInit();
dspFound = true;
loadSoundEffects();
playMusic();
}
// Loop as long as the status is not exit
while (aptMainLoop() && !exiting)
{
@@ -87,6 +121,14 @@ int main()
C3D_FrameEnd(0);
gspWaitForVBlank();
}
if (songIsFound == true) {
stopMusic();
}
delete bgm;
if (dspFound == true) {
ndspExit();
}
Config::save();
Gui::exit();
gfxExit();
+133
View File
@@ -0,0 +1,133 @@
#include "utils/sound.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
using std::string;
// Reference: http://yannesposito.com/Scratch/en/blog/2010-10-14-Fun-with-wav/
typedef struct _WavHeader {
char magic[4]; // "RIFF"
u32 totallength; // Total file length, minus 8.
char wavefmt[8]; // Should be "WAVEfmt "
u32 format; // 16 for PCM format
u16 pcm; // 1 for PCM format
u16 channels; // Channels
u32 frequency; // Sampling frequency
u32 bytes_per_second;
u16 bytes_by_capture;
u16 bits_per_sample;
char data[4]; // "data"
u32 bytes_in_data;
} WavHeader;
static_assert(sizeof(WavHeader) == 44, "WavHeader size is not 44 bytes.");
sound::sound(const string& path, int channel, bool toloop)
{
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
ndspSetOutputCount(2); // Num of buffers
// Reading wav file
FILE* fp = fopen(path.c_str(), "rb");
if (!fp) {
printf("Could not open the WAV file: %s\n", path.c_str());
return;
}
WavHeader wavHeader;
size_t read = fread(&wavHeader, 1, sizeof(wavHeader), fp);
if (read != sizeof(wavHeader)) {
// Short read.
printf("WAV file header is too short: %s\n", path.c_str());
fclose(fp);
return;
}
// Verify the header.
static const char RIFF_magic[4] = {'R','I','F','F'};
if (memcmp(wavHeader.magic, RIFF_magic, sizeof(wavHeader.magic)) != 0) {
// Incorrect magic number.
printf("Wrong file format.\n");
fclose(fp);
return;
}
if (wavHeader.totallength == 0 ||
(wavHeader.channels != 1 && wavHeader.channels != 2) ||
(wavHeader.bits_per_sample != 8 && wavHeader.bits_per_sample != 16))
{
// Unsupported WAV file.
printf("Corrupted wav file.\n");
fclose(fp);
return;
}
// Get the file size.
fseek(fp, 0, SEEK_END);
dataSize = ftell(fp) - sizeof(wavHeader);
// Allocating and reading samples
data = static_cast<u8*>(linearAlloc(dataSize));
fseek(fp, 44, SEEK_SET);
fread(data, 1, dataSize, fp);
fclose(fp);
dataSize /= 2; // FIXME: 16-bit or stereo?
// Find the right format
u16 ndspFormat;
if (wavHeader.bits_per_sample == 8) {
ndspFormat = (wavHeader.channels == 1) ?
NDSP_FORMAT_MONO_PCM8 :
NDSP_FORMAT_STEREO_PCM8;
} else {
ndspFormat = (wavHeader.channels == 1) ?
NDSP_FORMAT_MONO_PCM16 :
NDSP_FORMAT_STEREO_PCM16;
}
ndspChnReset(channel);
ndspChnSetInterp(channel, NDSP_INTERP_NONE);
ndspChnSetRate(channel, float(wavHeader.frequency));
ndspChnSetFormat(channel, ndspFormat);
// Create and play a wav buffer
memset(&waveBuf, 0, sizeof(waveBuf));
waveBuf.data_vaddr = reinterpret_cast<u32*>(data);
waveBuf.nsamples = dataSize / (wavHeader.bits_per_sample >> 3);
waveBuf.looping = toloop;
waveBuf.status = NDSP_WBUF_FREE;
chnl = channel;
}
sound::~sound()
{
waveBuf.data_vaddr = 0;
waveBuf.nsamples = 0;
waveBuf.looping = false;
waveBuf.status = 0;
ndspChnWaveBufClear(chnl);
if (data) {
linearFree(data);
}
}
void sound::play()
{
if (!data)
return;
DSP_FlushDataCache(data, dataSize);
ndspChnWaveBufAdd(chnl, &waveBuf);
}
void sound::stop()
{
if (!data)
return;
ndspChnWaveBufClear(chnl);
}