Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

akmenu Streaming Audio #1043

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion romsel_aktheme/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,16 @@
"filesystem": "cpp",
"chrono": "cpp",
"codecvt": "cpp",
"ratio": "cpp"
"ratio": "cpp",
"atomic": "cpp",
"bit": "cpp",
"compare": "cpp",
"concepts": "cpp",
"iterator": "cpp",
"memory_resource": "cpp",
"random": "cpp",
"iostream": "cpp",
"ranges": "cpp"
},
"C_Cpp.intelliSenseEngineFallback": "Disabled",
"C_Cpp.errorSquiggles": "Disabled"
Expand Down
1 change: 1 addition & 0 deletions romsel_aktheme/arm7/source/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ int main() {
fifoInit();
touchInit();

mmInstall(FIFO_MAXMOD);
SetYtrigger(80);

installSoundFIFO();
Expand Down
4 changes: 2 additions & 2 deletions romsel_aktheme/arm9/source/irqs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "windows/batteryicon.h"
#include "windows/volumeicon.h"
#include "ui/animation.h"
#include "sound.h"

// #include "time/timer.h"
#include "common/files.h"
Expand Down Expand Up @@ -107,8 +108,7 @@ void IRQ::vBlank()
#endif

gdi().present(GE_SUB);
}

}
animationManager().update();

// if( REG_ROMCTRL & CARD_BUSY )
Expand Down
8 changes: 4 additions & 4 deletions romsel_aktheme/arm9/source/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
#include "common/dsimenusettings.h"
#include "common/flashcard.h"
#include "common/filecopy.h"

#include "sound.h"
// -- AK End ------------

#include <stdio.h>
Expand Down Expand Up @@ -137,7 +137,6 @@ int main(int argc, char **argv)
sfn().initFilenames();
nocashMessage("sfn init");
irq().init();

gdi().init();
// init graphics
gdi().initBg(SFN_LOWER_SCREEN_BG);
Expand Down Expand Up @@ -237,14 +236,15 @@ int main(int argc, char **argv)

//if (!wnd->_mainList->enterDir(SPATH_ROOT != lastDirectory ? lastDirectory : gs().startupFolder))
wnd->_mainList->enterDir(ms().romfolder[ms().secondaryDevice]);

snd().beginStream();
irq().vblankStart();

while (1)
{
// snd().updateStream();
timer().updateFps();
INPUT &inputs = updateInput();
processInput(inputs);
snd().updateStream();
swiWaitForVBlank();
windowManager().update();
gdi().present(GE_MAIN);
Expand Down
177 changes: 177 additions & 0 deletions romsel_aktheme/arm9/source/sound.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#include "sound.h"

#include "systemfilenames.h"
#include "streamingaudio.h"
#include "string.h"
#include "common/tonccpy.h"
#include <algorithm>

#define SFX_STARTUP 0

#define MSL_NSONGS 0
#define MSL_NSAMPS 1
#define MSL_BANKSIZE 1


extern volatile s16 fade_counter;
extern volatile bool fade_out;

extern volatile s16* play_stream_buf;
extern volatile s16* fill_stream_buf;

// Number of samples filled into the fill buffer so far.
extern volatile s32 filled_samples;

extern volatile bool fill_requested;
extern volatile long streamed_samples;
extern volatile s32 streaming_buf_ptr;

#define SAMPLES_USED (STREAMING_BUF_LENGTH - samples_left)
#define REFILL_THRESHOLD STREAMING_BUF_LENGTH >> 2

#ifdef SOUND_DEBUG
extern char debug_buf[256];
#endif

extern volatile u32 sample_delay_count;

// volatile char SFX_DATA[0x7D000] = {0};
mm_word SOUNDBANK[MSL_BANKSIZE] = {0};

SoundControl::SoundControl()
: stream_is_playing(false), stream_source(NULL), startup_sample_length(0)
{

sys.mod_count = MSL_NSONGS;
sys.samp_count = MSL_NSAMPS;
sys.mem_bank = SOUNDBANK;
sys.fifo_channel = FIFO_MAXMOD;

// FILE* soundbank_file;
// soundbank_file = fopen(std::string(SFN_SOUND_EFFECTBANK).c_str(), "rb");

// fread((void*)SFX_DATA, 1, sizeof(SFX_DATA), soundbank_file);

// fclose(soundbank_file);

// // Since SFX_STARTUP is the first sample, it begins at 0x10 after the
// // *maxmod* header. Subtract the size of the sample header,
// // and divide by two to get length in samples.
// // https://github.com/devkitPro/mmutil/blob/master/source/msl.c#L80

// startup_sample_length = (((*(u32*)(SFX_DATA + 0x10)) - 20) >> 1);

// sprintf(debug_buf, "Read sample length %li for startup", startup_sample_length);
// nocashMessage(debug_buf);

mmInit(&sys);

// mmSoundBankInMemory((mm_addr)SFX_DATA);
// mmLoadEffect(SFX_STARTUP);

// mus_startup = {
// {SFX_STARTUP}, // id
// (int)(1.0f * (1 << 10)), // rate
// 0, // handle
// 255, // volume
// 128, // panning
// };
stream_source = fopen(std::string(SFN_SOUND_BG).c_str(), "rb");
fseek((FILE*)stream_source, 0, SEEK_SET);

stream.sampling_rate = 16000; // 16000Hz
stream.buffer_length = 400; // should be adequate
stream.callback = on_stream_request;
stream.format = MM_STREAM_16BIT_MONO; // select format
stream.timer = MM_TIMER0; // use timer0
stream.manual = false; // auto filling

// Prep the first section of the stream
fread((void*)play_stream_buf, sizeof(s16), STREAMING_BUF_LENGTH, (FILE*)stream_source);

// Fill the next section premptively
fread((void*)fill_stream_buf, sizeof(s16), STREAMING_BUF_LENGTH, (FILE*)stream_source);

}

void SoundControl::beginStream() {
// open the stream
stream_is_playing = true;
mmStreamOpen(&stream);
SetYtrigger(0);
}

void SoundControl::stopStream() {
stream_is_playing = false;
mmStreamClose();
}

void SoundControl::fadeOutStream() {
fade_out = true;
}

void SoundControl::cancelFadeOutStream() {
fade_out = false;
fade_counter = FADE_STEPS;
}

void SoundControl::setStreamDelay(u32 delay) {
sample_delay_count = delay;
}


// Samples remaining in the fill buffer.
#define SAMPLES_LEFT_TO_FILL (abs(STREAMING_BUF_LENGTH - filled_samples))

// Samples that were already streamed and need to be refilled into the buffer.
#define SAMPLES_TO_FILL (abs(streaming_buf_ptr - filled_samples))

// Updates the background music fill buffer
// Fill the amount of samples that were used up between the
// last fill request and this.

// Precondition Invariants:
// filled_samples <= STREAMING_BUF_LENGTH
// filled_samples <= streaming_buf_ptr

// Postcondition Invariants:
// filled_samples <= STREAMING_BUF_LENGTH
// filled_samples <= streaming_buf_ptr
// fill_requested == false
volatile void SoundControl::updateStream() {
if (!stream_is_playing) return;
if (fill_requested && filled_samples < STREAMING_BUF_LENGTH) {
// Reset the fill request
fill_requested = false;
int instance_filled = 0;

// Either fill the max amount, or fill up the buffer as much as possible.
int instance_to_fill = streamed_samples;
streamed_samples = 0;

// If we don't read enough samples, loop from the beginning of the file.
instance_filled = fread((s16*)fill_stream_buf + filled_samples, sizeof(s16), instance_to_fill, (FILE*)stream_source);


if (instance_filled < instance_to_fill) {
fseek((FILE*)stream_source, 0, SEEK_SET);
instance_filled += fread((s16*)fill_stream_buf + filled_samples + instance_filled,
sizeof(s16), (instance_to_fill - instance_filled), (FILE*)stream_source);
}


#ifdef SOUND_DEBUG
sprintf(debug_buf, "FC: SAMPLES_LEFT_TO_FILL: %li, SAMPLES_TO_FILL: %li, instance_filled: %i, filled_samples %li, to_fill: %i", SAMPLES_LEFT_TO_FILL, SAMPLES_TO_FILL, instance_filled, filled_samples, instance_to_fill);
nocashMessage(debug_buf);
#endif

// maintain invariant 0 < filled_samples <= STREAMING_BUF_LENGTH
filled_samples = std::min<s32>(filled_samples + instance_filled, STREAMING_BUF_LENGTH);
} else if (fill_requested && filled_samples >= STREAMING_BUF_LENGTH) {
// filled_samples == STREAMING_BUF_LENGTH is the only possible case
// but we'll keep it at gte to be safe.
filled_samples = 0;
// fill_count = 0;
}

}
46 changes: 46 additions & 0 deletions romsel_aktheme/arm9/source/sound.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once
#ifndef __TWILIGHTMENU_SOUND__
#define __TWILIGHTMENU_SOUND__
#include <nds.h>
#include <mm_types.h>
#include <maxmod9.h>
#include "common/singleton.h"
#include <cstdio>

/*
* Handles playing sound effects and the streaming background music control.
* See streamingaudio.c for a technical overview of how streaming works.
*/
class SoundControl {
public:
SoundControl();
mm_sfxhand playStartup();

// Refill the stream buffers
volatile void updateStream();

void beginStream();
void stopStream();
void fadeOutStream();
void cancelFadeOutStream();

// Sets the number of samples of silence to
// stream before continuing.
void setStreamDelay(u32 stream_delay);

u32 getStartupSoundLength() { return startup_sample_length; }

private:
mm_stream stream;
mm_ds_system sys;
volatile bool stream_is_playing;
//mm_sound_effect snd_loading;
mm_sound_effect mus_startup;
volatile FILE* stream_source;
u32 startup_sample_length;
};

typedef singleton<SoundControl> soundCtl_s;
inline SoundControl &snd() { return soundCtl_s::instance(); }

#endif
Loading