Notice: This version is for testing only. It may cause unwanted side effects for the sound in many games. It adds preliminary support for volume control. I think high delta values (often close to 0x10000) mean that volume should be lowered, and vice versa. But I'm unsure how big the volume steps should be, and where the volume should go to. The current guess is that pb.mixer_control also tell us what the new volume level should be, but I'm not sure about that. The current settings seems to work okay in games like Paper Mario and Fire Emblem when sounds are faded in to begin or faded out to stop. But it worked less well for the sequenced music in Skies of Arcadia where some blocks would get a to high volume.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@806 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2008-10-09 04:00:47 +00:00
parent 3d20ad60d9
commit 4001e11116
6 changed files with 451 additions and 244 deletions

View file

@ -198,7 +198,7 @@ SetTitle(wxT("Sound Debugging"));
m_RadioBox[1] = new wxRadioBox( this, IDC_RADIO1, wxT("Update freq."),
wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[1], m_radioBoxChoices1, 1, wxRA_SPECIFY_COLS);
wxString m_radioBoxChoices2[] = { wxT("Preset 1"), wxT("Preset 2"), wxT("Preset 3") };
wxString m_radioBoxChoices2[] = { wxT("Preset 1"), wxT("Updates"), wxT("Looping"), wxT("Mixer") };
m_radioBoxNChoices[2] = sizeof( m_radioBoxChoices2 ) / sizeof( wxString );
m_RadioBox[2] = new wxRadioBox( this, IDC_RADIO2, wxT("Presets"),
wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[2], m_radioBoxChoices2, 1, wxRA_SPECIFY_COLS);
@ -346,7 +346,7 @@ void CDebugger::DoChangePreset()
}
else if(m_RadioBox[2]->GetSelection() == 3)
{
gPreset = 9;
gPreset = 3;
}
}
// ==============

View file

@ -16,7 +16,8 @@
// http://code.google.com/p/dolphin-emu/
// --------------------
// Includes
#include <string>
#include <stdio.h>
#ifdef _WIN32
@ -24,40 +25,39 @@
#endif
// --------------------
// On and off
bool g_consoleEnable = true;
int gSaveFile = 0;
#define DEBUGG
//#define DEBUGG_FILEONLY
// --------------------
// Settings
int nFiles = 4;
// --------------------
// Create handles
#ifdef DEBUGG
FILE* __fStdOut = NULL;
FILE* __fStdOut[4]; // you have to update this manually, we can't place a nFiles in there
#endif
#ifndef DEBUGG_FILEONLY
#ifdef _WIN32
HANDLE __hStdOut = NULL;
#endif
#endif
// --------------------
// =======================================================================================
/* Start console window - width and height is the size of console window, if you specify
fname, the output will also be writton to this file. The file pointer is automatically
closed when you close the app */
// ---------------------------------------------------------------------------------------
fname, the output will also be written to this file. TODO: Close the file pointer when the app
is closed */
// -------------
void startConsoleWin(int width, int height, char* fname)
{
#if defined(DEBUGG) && defined(_WIN32)
#ifndef DEBUGG_FILEONLY
AllocConsole();
SetConsoleTitle(fname);
@ -69,53 +69,79 @@ void startConsoleWin(int width, int height, char* fname)
SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
#endif
// ---------------------------------------------------------------------------------------
// Write to a file
if(fname)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = fname;
std::string FullFilename = (FileName + FileEnding);
__fStdOut = fopen(FullFilename.c_str(), "w");
for(int i = 0; i < nFiles; i++)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = fname;
char buffer[33]; itoa(i, buffer, 10); // convert number to string
std::string FullFilename = (FileName + buffer + FileEnding);
__fStdOut[i] = fopen(FullFilename.c_str(), "w");
}
}
// ---------------------------------------------------------------------------------------
// ---------------
#endif
}
// ---------------------------------------------------------------------------------------
// Printf function
// File printf function
int aprintf(int a, char *fmt, ...)
{
#if defined(DEBUGG) && defined(_WIN32)
if(gSaveFile)
{
char s[5000]; // WARNING: mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 5000, fmt, argptr); // remember to update this value to
va_end(argptr);
// ---------------------------------------------------------------------------------------
if(__fStdOut[a]) // TODO: make this work, we have to set all default values to NULL
//to make it work
fprintf(__fStdOut[a], s);
// -------------
return(cnt);
}
else
{
return 0;
}
#else
return 0;
#endif
}
// ---------------------------------------------------------------------------------------
// Printf to screen function
int wprintf(char *fmt, ...)
{
#if defined(DEBUGG) && defined(_WIN32)
char s[7000]; // WARNING: Mind this value
char s[5000]; // WARNING: mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 3000, fmt, argptr);
cnt = vsnprintf(s, 5000, fmt, argptr);
va_end(argptr);
DWORD cCharsWritten;
// ---------------------------------------------------------------------------------------
#ifndef DEBUGG_FILEONLY
if(__hStdOut)
{
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
}
#endif
// -------------
// ---------------------------------------------------------------------------------------
if(gSaveFile)
{
if(__fStdOut)
fprintf(__fStdOut, s);
}
// -------------
return(cnt);

View file

@ -18,6 +18,7 @@
void startConsoleWin(int width, int height, char* fname);
int wprintf(char *fmt, ...);
int aprintf(int a, char *fmt, ...);
void ClearScreen();
void OpenConsole();
void CloseConsole();

View file

@ -27,6 +27,7 @@
#include <iostream>
#include <vector>
#include <string> // so that we can test std::string == abc
#include <math.h> // for the pow() function
#ifdef _WIN32
#include <windows.h>
#endif
@ -43,6 +44,7 @@
// Externals
extern int nFiles;
float ratioFactor; // a global to get the ratio factor from MixAdd
int gUpdFreq = 5;
int gPreset = 0;
@ -57,9 +59,13 @@ extern int gSaveFile;
// Parameter blocks
std::vector<u32> gloopPos(64);
std::vector<u32> gsampleEnd(64);
std::vector<u32> gsamplePos(64);
std::vector<u32> gloopPos(64);
std::vector<u32> gsampleEnd(64);
std::vector<u32> gsamplePos(64);
// main
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
// PBSampleRateConverter src
std::vector<u32> gratio(64);
@ -70,20 +76,39 @@ std::vector<u32> gsamplePos(64);
// PBSampleRateConverter mixer
std::vector<u16> gvolume_left(64);
std::vector<u16> gmix_unknown(64);
std::vector<u16> gvolume_right(64);
std::vector<u16> gmix_unknown2(64);
std::vector<u16> gmixer_control(64);
std::vector<u16> gmixer_vol1(64);
std::vector<u16> gmixer_vol2(64);
std::vector<u16> gmixer_vol3(64);
std::vector<u16> gmixer_vol4(64);
std::vector<u16> gmixer_vol5(64);
std::vector<u16> gmixer_vol6(64);
std::vector<u16> gmixer_vol7(64);
std::vector<u16> gmixer_d1(64);
std::vector<u16> gmixer_d2(64);
std::vector<u16> gmixer_d3(64);
std::vector<u16> gmixer_d4(64);
std::vector<u16> gmixer_d5(64);
std::vector<u16> gmixer_d6(64);
std::vector<u16> gmixer_d7(64);
// PBVolumeEnvelope vol_env
std::vector<u16> gcur_volume(64);
std::vector<u16> gcur_volume_delta(64);
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
// loop
// PBAudioAddr audio_addr (incl looping)
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gloop1(64);
std::vector<u16> gloop2(64);
std::vector<u16> gloop3(64);
// PBADPCMInfo adpcm
std::vector<u16> gadloop1(64);
std::vector<u16> gadloop2(64);
std::vector<u16> gadloop3(64);
@ -95,15 +120,14 @@ std::vector<u16> gis_stream(64);
std::vector<u16> gupdates4(64);
std::vector<u16> gupdates5(64);
std::vector<u32> gupdates_addr(64);
std::vector<u32> gupdates_data(64);
// Counters
int j = 0;
int k = 0;
long int l = 0;
unsigned int l = 0;
int iupd = 0;
bool iupdonce = false;
std::vector<u16> viupd(15); // the length of the update frequency bar
@ -127,6 +151,112 @@ extern CDebugger* m_frame;
// =======================================================================================
// Write title
// --------------
std::string writeTitle(int a)
{
std::string b;
if(a == 0)
{
b = " adpcm adpcm_loop\n";
b = b + " Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo]\n";
}
else if(a == 1)
{
b = " Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5\n";
}
else if(a == 2)
{
b = " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n";
}
else if(a == 3)
{
b = " Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n";
}
return b;
}
// =======================================================================================
// =======================================================================================
// Write main message (presets)
// --------------
std::string writeMessage(int a, int i)
{
char buf [1000] = "";
std::string sbuf;
// =======================================================================================
// PRESETS
// ---------------------------------------------------------------------------------------
/*
PRESET 0
" Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo]\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0 0 | 000 00000 00000 000 00000 00000 | 00000 00000[0 00000]
PRESET 1 (updates)
" Nr pos / end lpos | voll volr | src form coef | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0 0 0 | 0 0 0 0 0
PRESET 2
" Nr pos / end lpos | voll volr | isl iss | e-l e-s\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0 0 | 000000 000000
*/
if(a == 0)
{
sprintf(buf,"%c%02i %08i/%08i %08i | %05i %05i | %i %i | %03i %05i %05i %03i %05i %05i | %05i %05i[%i %05i]",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
glooping[i], gis_stream[i],
gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i],
gfrac[i], gratio[i], gratiohi[i], gratiolo[i]
);
}
else if(a == 1)
{
sprintf(buf,"%c%02i %08i/%08i %08i | %05i %05i | %i %i %i | %i %i %i %i %i %08x %08x",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
gsrc_type[i], gaudioFormat[i], gcoef[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i], gupdates_addr[i], gupdates_data[i]
);
}
else if(a == 2)
{
sprintf(buf,"%c%02i %08i/%08i %08i | %05i %05i | %i %i | %06i %06i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
glooping[i], gis_stream[i],
gsampleEnd[i] - gloopPos[i], gsampleEnd[i] - gsamplePos[i]
);
}
/*
PRESET 3
" Nr voll volr dl dr curv delt mixc r | v1 v2 v3 v4 v5 v6 v7 | d1 d2 d3 d4 d5 d6 d7\n";
"---------------|00 00000 00000 00000 00000 00000 00000 00000 0 | 00000 00000 00000 00000 00000 00000 00000 | 00000 00000 00000 00000 00000 00000 00000
*/
else if(a == 3)
{
sprintf(buf,"%c%02i %05i %05i %05i %05i %05i %05i %05i %i | %05i %05i %05i %05i %05i %05i %05i | %05i %05i %05i %05i %05i %05i %05i",
223, i,
gvolume_left[i], gvolume_right[i], gmix_unknown[i], gmix_unknown2[i], gcur_volume[i], gcur_volume_delta[i],
gmixer_control[i], (gmixer_control[i] & MIXCONTROL_RAMPING),
gmixer_vol1[i], gmixer_vol2[i], gmixer_vol3[i], gmixer_vol4[i], gmixer_vol5[i],
gmixer_vol6[i], gmixer_vol7[i],
gmixer_d1[i], gmixer_d2[i], gmixer_d3[i], gmixer_d4[i], gmixer_d5[i],
gmixer_d6[i], gmixer_d7[i]
);
}
sbuf = buf;
return sbuf;
}
// =======================================================================================
// I placed this in CUCode_AX because it needs access to private members of that class.
void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
{
@ -134,10 +264,138 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
AXParamBlock PBs[NUMBER_OF_PBS];
int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS);
// Control how often the screen is updated
j++;
l++;
// =======================================================================================
// Update parameter values
// --------------
// We could chose to update these only if a block is currently running - Later I'll add options
// to see both the current and the lastets active value.
//if (PBs[i].running)
int irun = 0;
for (int i = 0; i < numberOfPBs; i++)
{
if(PBs[i].running)
{
irun++;
}
// write a line if nothing is playing
if (i == numberOfPBs - 1 && irun == 0)
{
for (int i = 0; i < nFiles; i++)
{
std::string sfbuff;
sfbuff = "-----";
aprintf(i, (char *)sfbuff.c_str());
}
}
// ---------------------------------------------------------------------------------------
// Prepare conditions
// --------------
bool Conditions;
if (gOnlyLooping)
{
Conditions = PBs[i].audio_addr.looping;
}
else
{
Conditions = (numberRunning.at(i) > 0 || PBs[i].audio_addr.looping);
}
// --------------
if(Conditions)
{
// AXPB base
gcoef[i] = PBs[i].unknown1;
gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo;
gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo;
gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo;
// PBSampleRateConverter src
gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor);
gratiohi[i] = PBs[i].src.ratio_hi;
gratiolo[i] = PBs[i].src.ratio_lo;
gfrac[i] = PBs[i].src.cur_addr_frac;
// adpcm_loop_info
gadloop1[i] = PBs[i].adpcm.pred_scale;
gadloop2[i] = PBs[i].adpcm.yn1;
gadloop3[i] = PBs[i].adpcm.yn2;
gloop1[i] = PBs[i].adpcm_loop_info.pred_scale;
gloop2[i] = PBs[i].adpcm_loop_info.yn1;
gloop3[i] = PBs[i].adpcm_loop_info.yn2;
// updates
gupdates1[i] = PBs[i].updates.num_updates[0];
gupdates2[i] = PBs[i].updates.num_updates[1];
gupdates3[i] = PBs[i].updates.num_updates[2];
gupdates4[i] = PBs[i].updates.num_updates[3];
gupdates5[i] = PBs[i].updates.num_updates[4];
gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo;
gupdates_data[i] = Memory_Read_U32(gupdates_addr[i]);
gaudioFormat[i] = PBs[i].audio_addr.sample_format;
glooping[i] = PBs[i].audio_addr.looping;
gsrc_type[i] = PBs[i].src_type;
gis_stream[i] = PBs[i].is_stream;
// mixer
gvolume_left[i] = PBs[i].mixer.volume_left;
gvolume_right[i] = PBs[i].mixer.volume_right;
gmix_unknown[i] = PBs[i].mixer.unknown;
gmix_unknown2[i] = PBs[i].mixer.unknown2;
gmixer_control[i] = PBs[i].mixer_control;
gcur_volume[i] = PBs[i].vol_env.cur_volume;
gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta;
gmixer_vol1[i] = PBs[i].mixer.unknown3[0];
gmixer_vol2[i] = PBs[i].mixer.unknown3[2];
gmixer_vol3[i] = PBs[i].mixer.unknown3[4];
gmixer_vol4[i] = PBs[i].mixer.unknown3[6];
gmixer_vol5[i] = PBs[i].mixer.unknown3[0];
gmixer_vol6[i] = PBs[i].mixer.unknown3[2];
gmixer_vol7[i] = PBs[i].mixer.unknown3[4];
gmixer_d1[i] = PBs[i].mixer.unknown4[1];
gmixer_d2[i] = PBs[i].mixer.unknown4[3];
gmixer_d3[i] = PBs[i].mixer.unknown4[5];
gmixer_d4[i] = PBs[i].mixer.unknown4[7];
gmixer_d5[i] = PBs[i].mixer.unknown4[1];
gmixer_d6[i] = PBs[i].mixer.unknown4[3];
gmixer_d7[i] = PBs[i].mixer.unknown4[5];
// ---------------------------------------------------------------------------------------
// Write to file
// --------------
for (int ii = 0; ii < nFiles; ii++)
{
std::string sfbuff;
if(a == 0) sfbuff = "***"; // note if it's before or after an update
else sfbuff = " ";
sfbuff = sfbuff + writeMessage(ii, i);
sfbuff = sfbuff + "\n";
aprintf(ii, (char *)sfbuff.c_str());
}
// --------------
}
}
// ==============
// =======================================================================================
// Control how often the screen is updated, and then update the screen
// --------------
if(a == 0) j++;
//if(l == pow((double)2,32)) l=0; // reset l
//l++;
if (j > (200/gUpdFreq))
{
@ -156,11 +414,9 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
{
vector1.at(i).at(j-1) = vector1.at(i).at(j);
}
}
// Save the latest value
}
// Save the latest value
for (int i = 0; i < numberOfPBs; i++)
{
vector1.at(i).at(vectorLength-1) = PBs[i].running ? true : false;
@ -183,11 +439,9 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
{
vector2.at(i).at(j-1) = vector2.at(i).at(j);
}
}
// Save the latest value
}
// Save the latest value
for (int i = 0; i < numberOfPBs; i++)
{
vector2.at(i).at(vectorLength2-1) = PBs[i].running;
@ -218,34 +472,16 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
// --------------
char buffer [1000] = "";
std::string sbuff;
if(gPreset == 0)
{
sbuff = sbuff + " adpcm adpcm_loop\n";
sbuff = sbuff + " Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo] | 1 2 3 4 5\n";
}
else if(gPreset == 1)
{
sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold | src coef mixc\n";
}
else if(gPreset == 2)
{
sbuff = sbuff + " Nr pos / end lpos | voll volr | isl iss | e-l e-s\n";
}
sbuff = writeTitle(gPreset);
// ==============
// go through all running blocks
for (int i = 0; i < numberOfPBs; i++)
{
// =======================================================================================
// Prepare conditions
// ---------------------------------------------------------------------------------------
// Prepare conditions. TODO: We use this in two places now, make it only one
// --------------
bool Conditions;
if (gOnlyLooping)
@ -256,8 +492,10 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
{
Conditions = (numberRunning.at(i) > 0 || PBs[i].audio_addr.looping);
}
// ==============
// --------------
// use the condition
if (Conditions)
{
@ -309,59 +547,6 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
// ---------
// We could chose to update these only if a block is currently running - Later I'll add options
// to see both the current and the lastets active value.
//if (PBs[i].running)
if (true)
{
// AXPB base
gcoef[i] = PBs[i].unknown1;
gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo;
gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo;
gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo;
// PBSampleRateConverter src
gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor);
gratiohi[i] = PBs[i].src.ratio_hi;
gratiolo[i] = PBs[i].src.ratio_lo;
gfrac[i] = PBs[i].src.cur_addr_frac;
// adpcm_loop_info
gadloop1[i] = PBs[i].adpcm.pred_scale;
gadloop2[i] = PBs[i].adpcm.yn1;
gadloop3[i] = PBs[i].adpcm.yn2;
gloop1[i] = PBs[i].adpcm_loop_info.pred_scale;
gloop2[i] = PBs[i].adpcm_loop_info.yn1;
gloop3[i] = PBs[i].adpcm_loop_info.yn2;
// updates
gupdates1[i] = PBs[i].updates.num_updates[0];
gupdates2[i] = PBs[i].updates.num_updates[1];
gupdates3[i] = PBs[i].updates.num_updates[2];
gupdates4[i] = PBs[i].updates.num_updates[3];
gupdates5[i] = PBs[i].updates.num_updates[4];
gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo;
gaudioFormat[i] = PBs[i].audio_addr.sample_format;
glooping[i] = PBs[i].audio_addr.looping;
gsrc_type[i] = PBs[i].src_type;
gis_stream[i] = PBs[i].is_stream;
// mixer
gvolume_left[i] = PBs[i].mixer.volume_left;
gvolume_right[i] = PBs[i].mixer.volume_right;
gmixer_control[i] = PBs[i].mixer_control;
gcur_volume[i] = PBs[i].vol_env.cur_volume;
gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta;
}
// hopefully this is false if we don't have a debugging window and so it doesn't cause a crash
if(m_frame)
{
@ -396,54 +581,8 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
m_frame->m_GPRListView->m_CachedRegs[22][i] = gupdates5[i];
}
// =======================================================================================
// PRESETS
// ---------------------------------------------------------------------------------------
/*
PRESET 0
" Nr pos / end lpos | voll volr | isl iss | pre yn1 yn2 pre yn1 yn2 | frac ratio[hi lo] | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0 0 | 000 00000 00000 000 00000 00000 | 00000 00000[0 00000] |
PRESET 1
" Nr pos / end lpos | voll volr curv vold | src coef mixc\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 00000 00000 | 0 0 0
PRESET 2
" Nr pos / end lpos | voll volr | isl iss | e-l e-s\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0 0 | 000000 000000
*/
if(gPreset == 0)
{
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i | %i %i | %03i %05i %05i %03i %05i %05i | %05i %05i[%i %05i] | %i %i %i %i %i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
glooping[i], gis_stream[i],
gadloop1[i], gadloop2[i], gadloop3[i], gloop1[i], gloop2[i], gloop3[i],
gfrac[i], gratio[i], gratiohi[i], gratiolo[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i]
);
}
else if(gPreset == 1)
{
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i %05i %05i | %i %i %i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i], gcur_volume[i], gcur_volume_delta[i],
gsrc_type[i], gcoef[i], gmixer_control[i]
);
}
else if(gPreset == 2)
{
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i | %i %i | %06i %06i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
glooping[i], gis_stream[i],
gsampleEnd[i] - gloopPos[i], gsampleEnd[i] - gsamplePos[i]
);
}
// add new line
sbuff = sbuff + buffer; strcpy(buffer, "");
sbuff = sbuff + writeMessage(gPreset, i); strcpy(buffer, "");
sbuff = sbuff + "\n";
@ -522,29 +661,25 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a)
// =======================================================================================
// Print
// ---------------------------------------------------------------------------------------
// ----------------
ClearScreen();
// we'll always have one to many \n at the end, remove it
//wprintf("%s", sbuff.substr(0, sbuff.length()-1).c_str());
wprintf("%s", sbuff.c_str());
sbuff.clear(); strcpy(buffer, "");
// ================
// New values are written so update - DISABLED - It flickered a lot, even worse than a
// console window. I'll add a console window later to show the current status.
//if(m_frame)
if(false)
// console window. So for now only the console windows is updated.
/*
if(m_frame)
{
//m_frame->NotifyUpdate();
m_frame->NotifyUpdate();
}
*/
k=0;
j=0;
} // end of if (j>20)
} // end of if (j>20)
} // end of function

View file

@ -128,6 +128,31 @@ void ADPCM_Loop(AXParamBlock& pb)
//else stream and we should not attempt to replace values
}
// =======================================================================================
// Volume control (ramping)
// --------------
u16 ADPCM_Vol(u16 vol, u16 delta, u16 mixer_control)
{
int x = vol;
if (delta && delta < 0x4000)
x += delta; // unsure what the right step is
//x ++;
//x += 8; //?
else if (delta && delta > 0x4000)
//x -= (0x8000 - pb.mixer.unknown); // this didn't work
x--;
if (x < 0) x = 0; // make limits
// does this make any sense?
//if (pb.mixer_control < 1000 && x < pb.mixer_control) x = pb.mixer_control;
//if (x >= 0x7fff) xl = 0x7fff; // this seems to high
if (mixer_control > 1000 && x > mixer_control) x = mixer_control;
return x; // update volume
}
// ==============
void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
{
AXParamBlock PBs[NUMBER_OF_PBS];
@ -156,18 +181,22 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
{
AXParamBlock& pb = PBs[i];
// get necessary values
const u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo;
const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
const u32 updaddr = (u32)(pb.updates.data_hi << 16) | pb.updates.data_lo;
const u32 upddata = Memory_Read_U32(updaddr);
// =======================================================================================
/*
Fix problems introduced with the SSBM fix - Sometimes when a music stream ended sampleEnd
would become extremely high and the game would play random sound data from ARAM resulting in
a strange noise. This should take care of that. - Some games (Monkey Ball 1 and Tales of
Symphonia) also had one odd block with a strange high loopPos and strange num_updates values,
the loopPos limit turns those off also. - Please report any side effects.
Symphonia and other) also had one odd last block with a strange high loopPos and strange
num_updates values, the loopPos limit turns those off also. - Please report any side effects.
*/
// ------------
const u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo;
const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
if (
(sampleEnd > 0x10000000 || loopPos > 0x10000000)
&& gSSBMremedy1
@ -191,38 +220,38 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
/*
// the fact that no settings are reset (except running) after a SSBM type music stream or another
looping block (for example in Battle Stadium DON) has ended could cause loud garbled sound to be
played from one or more blocks. Battle Stadium DON would usually have as much as five short looping
sounds (for example for running water and other things), but one or more of those would turn in to
looping noise machines if the old SSBM fix (withouth the pb.mixer_control check) was applied. This
would fix that by resetting the values after a looping block had ended. But it would be at the price
of turing off all looping sounds except the music streams, it seemed. But hopefully with the improved
SSBM music fix this check is not needed. I'll save it for now but it may perhaps be deleted in the
future.
played from one or more blocks. Perhaps it was in conjunction with the old sequenced music fix below,
I'm not sure. This was an attempt to prevent that anyway by resetting all. But I'm not sure if this
is needed anymore. Please try to play SSBM without it and see if it works anyway.
*/
if (
// detect blocks that have recently been running that we should reset
pb.running == 0 && pb.audio_addr.looping == 1
//pb.running == 0 && pb.adpcm_loop_info.pred_scale
// this prevents us from ruining sequenced music blocks
// this prevents us from ruining sequenced music blocks, may not be needed
/*
&& !(pb.updates.num_updates[0] || pb.updates.num_updates[1] || pb.updates.num_updates[2]
|| pb.updates.num_updates[3] || pb.updates.num_updates[4])
*/
&& !upddata
&& pb.mixer_control == 0 // only use this in SSBM
&& gSSBMremedy2 // let us turn this fix on and off
)
{
// reset all values, or mostly all
pb.audio_addr.cur_addr_hi = 0; pb.audio_addr.cur_addr_lo = 0;
pb.audio_addr.end_addr_hi = 0; pb.audio_addr.end_addr_lo = 0;
pb.audio_addr.loop_addr_hi = 0; pb.audio_addr.loop_addr_lo = 0;
pb.src.cur_addr_frac = 0; PBs[i].src.ratio_hi = 0; PBs[i].src.ratio_lo = 0;
pb.adpcm.pred_scale = 0; pb.adpcm.yn1 = 0; pb.adpcm.yn2 = 0;
// reset the detection values
pb.audio_addr.looping = 0;
pb.adpcm_loop_info.pred_scale = 0;
pb.adpcm_loop_info.yn1 = 0; pb.adpcm_loop_info.yn2 = 0;
//pb.audio_addr.cur_addr_hi = 0; pb.audio_addr.cur_addr_lo = 0;
//pb.audio_addr.end_addr_hi = 0; pb.audio_addr.end_addr_lo = 0;
//pb.audio_addr.loop_addr_hi = 0; pb.audio_addr.loop_addr_lo = 0;
//pb.src.cur_addr_frac = 0; PBs[i].src.ratio_hi = 0; PBs[i].src.ratio_lo = 0;
//pb.adpcm.pred_scale = 0; pb.adpcm.yn1 = 0; pb.adpcm.yn2 = 0;
}
// =============
@ -233,17 +262,26 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
Sequenced music fix - Because SSBM type music and other (for example Battle Stadium DON) looping
blocks did no have its pred_scale (or any other parameter except running) turned off after a song
was stopped a pred_scale check here had the effect of turning those blocks on immediately after
the stopped. Because the pred_scale check caused these effects I'm trying the num_updates check
instead. Please report any side effects.
the stopped. One way to easily test this is to start a game in BS DON, wait for the Fight message
so that the loops begin, and then exit the game and you can see that the sound effects will
continue to play in the menus. That's not good. Because the pred_scale check caused these effects
I'm trying an update data check instead, it relieas on the assumption that all games that don't
use sequencing have blank memory at the update address so that upddata = 0 in those cases. That
turned out to now hold, many games that don't use sequencing still had update_addr pointing to
some memory location with data, either inside the parameter block space or close before or after
it.
*/
// ------------
//if (!pb.running && pb.adpcm_loop_info.pred_scale)
/**/
//if (!pb.running && pb.audio_addr.looping)
if (!pb.running && upddata)
/*
if (!pb.running &&
(pb.updates.num_updates[0] || pb.updates.num_updates[1] || pb.updates.num_updates[2]
|| pb.updates.num_updates[3] || pb.updates.num_updates[4])
&& gSequenced
)
)
*/
{
pb.running = 1;
}
@ -325,22 +363,6 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
// ==============
// =======================================================================================
// Streaming music and volume - The streaming music in Paper Mario use these settings:
// Base settings
// is_stream = 1
// src_type = 0
// PBAudioAddr
// audio_addr.looping = 1 (adpcm_loop_info.pred_scale = value, .yn1 = 0, .yn2 = 0)
/*
However. Some of the ingame music and seemingly randomly some other music incorrectly get
volume = 0 for both left and right. This also affects Fire Emblem. But Starfox Assault
that also use is_stream = 1 has no problem wuth the volume, but its settings are somewhat
different, it uses src_type = 1 and pb.src.ratio_lo (fraction) != 0
*/
// ==============
// =======================================================================================
// Walk through _iSize
for (int s = 0; s < _iSize; s++)
@ -402,10 +424,18 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
if (pb.mixer_control & MIXCONTROL_RAMPING)
{
int x = pb.vol_env.cur_volume;
x += pb.vol_env.cur_volume_delta;
x += pb.vol_env.cur_volume_delta; // I'm not sure about this, can anybody find a game
// that use this?
if (x < 0) x = 0;
if (x >= 0x7fff) x = 0x7fff;
pb.vol_env.cur_volume = x; // maybe not per sample?? :P
// strange way to not use this in Skies where it didn't work well
if(pb.mixer_control != 9 && pb.mixer_control != 123)
{
pb.mixer.volume_left = ADPCM_Vol(pb.mixer.volume_left, pb.mixer.unknown, pb.mixer_control);
pb.mixer.volume_right = ADPCM_Vol(pb.mixer.volume_right, pb.mixer.unknown2, pb.mixer_control);
}
}
int leftmix = pb.mixer.volume_left >> 5;
@ -459,6 +489,12 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
// write back out pbs
WriteBackPBs(PBs, numberOfPBs);
// write logging data to debugger again after the update
if(m_frame)
{
CUCode_AX::Logging(_pBuffer, _iSize, 1);
}
}
void CUCode_AX::Update()
@ -708,7 +744,7 @@ int CUCode_AX::ReadOutPBs(AXParamBlock* _pPBs, int _num)
break;
}
// return the number of readed PBs
// return the number of read PBs
return count;
}

View file

@ -61,14 +61,19 @@ std::vector<u32> gsamplePos(64);
std::vector<u32> gratiolo(64);
std::vector<u32> gfrac(64);
std::vector<u32> gcoef(64);
// PBSampleRateConverter mixer
std::vector<u16> gvolume_left(64);
std::vector<u16> gvolume_right(64);
std::vector<u16> gmixer_control(64);
std::vector<u16> gcur_volume(64);
std::vector<u16> gcur_volume_delta(64);
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
// loop
std::vector<u16> gloop1(64);
@ -175,7 +180,7 @@ void Logging()
char buffer [1000] = "";
std::string sbuff;
//sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5
sbuff = sbuff + " Nr pos / end lpos | voll volr | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
// --------------
@ -254,6 +259,10 @@ void Logging()
// mixer
gvolume_left[i] = PBs[i].mixer.volume_left;
gvolume_right[i] = PBs[i].mixer.volume_right;
gmixer_control[i] = PBs[i].mixer_control;
gcur_volume[i] = PBs[i].vol_env.cur_volume;
gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta;
// other stuff
Jump[i] = (gfrac[i] >> 16); // This is 1 or 0
@ -268,12 +277,12 @@ void Logging()
// PRESETS
// ---------------------------------------------------------------------------------------
/*
/" Nr pos / end lpos | voll volr | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] |
/" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] |
*/
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i | %i[%03i %05i %05i] %i | %05i %05i[%i %05i] | %i %i %i %i %i",
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i %05i %04i %05i | %i[%03i %05i %05i] %i | %05i %05i[%i %05i] | %i %i %i %i %i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i],
gvolume_left[i], gvolume_right[i], gcur_volume[i], gcur_volume_delta[i], gmixer_control[i],
glooping[i], gloop1[i], gloop2[i], gloop3[i], gis_stream[i],
gfrac[i], gratio[i], gratiohi[i], gratiolo[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i]