Merge branch 'AudioStreaming'

* AudioStreaming:
  Reset the stream playing flag on init.
  force VolumeDirectory to align files to 32KB (only streaming audio files really need to be aligned...)
  Removed the DTK Music option.  It is now always enabled.
  Added the response for audio streaming disc offset requests.  Generate an AI interrupt at the end of the audio streaming loop.  Fixes Pac-man Fever and the background music in Eternal Darkness.
  Fixed the erroneous looping in audio streaming games like Eternal Darkness and Zoids: Battle Legends.  Thanks for the tip, tueidj.
This commit is contained in:
skidau 2012-04-23 22:40:58 +10:00
commit 8878ae5fc3
13 changed files with 140 additions and 79 deletions

View File

@ -31,7 +31,6 @@ void AudioCommonConfig::Load()
IniFile file;
file.Load(File::GetUserPath(F_DSPCONFIG_IDX));
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
file.Get("Config", "EnableJIT", &m_EnableJIT, true);
file.Get("Config", "DumpAudio", &m_DumpAudio, false);
#if defined __linux__ && HAVE_ALSA
@ -53,7 +52,6 @@ void AudioCommonConfig::SaveSettings()
IniFile file;
file.Load(File::GetUserPath(F_DSPCONFIG_IDX));
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
file.Set("Config", "EnableJIT", m_EnableJIT);
file.Set("Config", "DumpAudio", m_DumpAudio);
file.Set("Config", "Backend", sBackend);
@ -67,7 +65,6 @@ void AudioCommonConfig::SaveSettings()
void AudioCommonConfig::Update() {
if (soundStream) {
soundStream->GetMixer()->SetThrottle(SConfig::GetInstance().m_Framelimit == 2);
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
soundStream->SetVolume(m_Volume);
}
}

View File

@ -33,7 +33,6 @@
struct AudioCommonConfig
{
bool m_EnableDTKMusic;
bool m_EnableJIT;
bool m_DumpAudio;
int m_Volume;

View File

@ -136,7 +136,6 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
if (m_AIplaying) {
Premix(samples, numLeft);
if (m_EnableDTKMusic)
AudioInterface::Callback_GetStreaming(samples, numLeft, m_sampleRate);
g_wave_writer.AddStereoSamples(samples, numLeft);
@ -147,12 +146,9 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
Premix(samples, numSamples);
// Add the DTK Music
if (m_EnableDTKMusic)
{
// Re-sampling is done inside
AudioInterface::Callback_GetStreaming(samples, numSamples, m_sampleRate);
}
}
Common::AtomicAdd(m_numSamples, -(s32)numLeft);

View File

@ -61,7 +61,6 @@ public:
unsigned int GetSampleRate() {return m_sampleRate;}
void SetThrottle(bool use) { m_throttle = use;}
void SetDTKMusic(bool use) { m_EnableDTKMusic = use;}
// TODO: do we need this
bool IsHLEReady() { return m_HLEready;}
@ -103,7 +102,6 @@ protected:
bool m_HLEready;
bool m_logAudio;
bool m_EnableDTKMusic;
bool m_throttle;
short m_buffer[MAX_SAMPLES * 2];

View File

@ -161,6 +161,7 @@ void LoadDefaultSSEState();
float MathFloatVectorSum(const std::vector<float>&);
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
// Tiny matrix/vector library.

View File

@ -19,6 +19,7 @@
#include "Common.h" // Common
#include "StringUtil.h"
#include "FileUtil.h"
#include "MathUtil.h"
#include "../HLE/HLE.h" // Core
#include "../PowerPC/PowerPC.h"
@ -68,7 +69,7 @@ void CBoot::Load_FST(bool _bIsWii)
u32 fstSize = VolumeHandler::Read32(0x0428) << shift;
u32 maxFstSize = VolumeHandler::Read32(0x042c) << shift;
u32 arenaHigh = 0x817FFFF4 - maxFstSize;
u32 arenaHigh = ROUND_DOWN(0x817FFFFF - maxFstSize, 0x20);
Memory::Write_U32(arenaHigh, 0x00000034);
// load FST

View File

@ -234,8 +234,8 @@ void Write32(const u32 _Value, const u32 _Address)
m_Control.PSTAT = tmpAICtrl.PSTAT;
g_LastCPUTime = CoreTiming::GetTicks();
// Tell Drive Interface to stop streaming
if (!tmpAICtrl.PSTAT) DVDInterface::g_bStream = false;
// Tell Drive Interface to start/stop streaming
DVDInterface::g_bStream = tmpAICtrl.PSTAT;
}
// AI Interrupt
@ -293,6 +293,11 @@ static void GenerateAudioInterrupt()
UpdateInterrupts();
}
void GenerateAISInterrupt()
{
GenerateAudioInterrupt();
}
void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate)
{
_AISampleRate = g_AISSampleRate;

View File

@ -43,6 +43,8 @@ void Write32(const u32 _iValue, const u32 _iAddress);
// Get the audio rates (48000 or 32000 only)
unsigned int GetAIDSampleRate();
void GenerateAISInterrupt();
} // namespace
#endif

View File

@ -28,6 +28,7 @@
#include "Thread.h"
#include "Memmap.h"
#include "../VolumeHandler.h"
#include "AudioInterface.h"
// Disc transfer rate measured in bytes per second
static const u32 DISC_TRANSFER_RATE_GC = 3125 * 1024;
@ -201,9 +202,11 @@ static UDICR m_DICR;
static UDIIMMBUF m_DIIMMBUF;
static UDICFG m_DICFG;
static u32 AudioStart;
static u32 LoopStart;
static u32 AudioPos;
static u32 AudioLength;
static u32 CurrentStart;
static u32 LoopLength;
static u32 CurrentLength;
u32 g_ErrorCode = 0;
bool g_bDiscInside = false;
@ -238,12 +241,16 @@ void DoState(PointerWrap &p)
p.Do(m_DIIMMBUF);
p.Do(m_DICFG);
p.Do(AudioStart);
p.Do(LoopStart);
p.Do(AudioPos);
p.Do(AudioLength);
p.Do(LoopLength);
p.Do(g_ErrorCode);
p.Do(g_bDiscInside);
p.Do(g_bStream);
p.Do(CurrentStart);
p.Do(CurrentLength);
}
void TransferComplete(u64 userdata, int cyclesLate)
@ -266,9 +273,13 @@ void Init()
m_DICFG.Hex = 0;
m_DICFG.CONFIG = 1; // Disable bootrom descrambler
AudioStart = 0;
AudioPos = 0;
AudioLength = 0;
LoopStart = 0;
LoopLength = 0;
CurrentStart = 0;
CurrentLength = 0;
g_bStream = false;
ejectDisc = CoreTiming::RegisterEvent("EjectDisc", EjectDiscCallback);
insertDisc = CoreTiming::RegisterEvent("InsertDisc", InsertDiscCallback);
@ -351,33 +362,46 @@ bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength)
bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
{
_iNumSamples &= ~31;
if (AudioPos == 0)
{
//MessageBox(0,"DVD: Trying to stream from 0", "bah", 0);
memset(_pDestBuffer, 0, _iNumSamples); // probably __AI_SRC_INIT :P
return false;
}
_iNumSamples &= ~31;
else
{
std::lock_guard<std::mutex> lk(dvdread_section);
VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples);
}
//
// FIX THIS
//
// loop check
//
AudioPos += _iNumSamples;
if (AudioPos >= AudioStart + AudioLength)
if (g_bStream)
{
g_bStream = false; // Starfox Adventures
AudioPos = AudioStart;
AudioPos += _iNumSamples;
if (AudioPos >= CurrentStart + CurrentLength)
{
if (LoopStart == 0)
{
AudioPos = 0;
CurrentStart = 0;
CurrentLength = 0;
}
else
{
AudioPos = LoopStart;
CurrentStart = LoopStart;
CurrentLength = LoopLength;
}
NGCADPCM::InitFilter();
AudioInterface::GenerateAISInterrupt();
}
//WARN_LOG(DVDINTERFACE,"ReadADPCM");
return true;
}
else
return false;
}
void Read32(u32& _uReturnValue, const u32 _iAddress)
@ -813,28 +837,69 @@ void ExecuteCommand(UDICR& _DICR)
// m_DICMDBUF[2].Hex = Length of the stream
case 0xE1:
{
// ugly hack to catch the disable command
if (m_DICMDBUF[1].Hex != 0)
u32 pos = m_DICMDBUF[1].Hex << 2;
u32 length = m_DICMDBUF[2].Hex;
// Start playing
if (!g_bStream && m_DICMDBUF[0].CMDBYTE1 == 0 && pos != 0 && length != 0)
{
AudioPos = m_DICMDBUF[1].Hex << 2;
AudioStart = AudioPos;
AudioLength = m_DICMDBUF[2].Hex;
AudioPos = pos;
CurrentStart = pos;
CurrentLength = length;
NGCADPCM::InitFilter();
g_bStream = true;
WARN_LOG(DVDINTERFACE, "(Audio) Stream subcmd = %02x offset = %08x length=%08x",
m_DICMDBUF[0].CMDBYTE1, AudioPos, AudioLength);
}
else
WARN_LOG(DVDINTERFACE, "(Audio) Off?");
LoopStart = pos;
LoopLength = length;
g_bStream = (m_DICMDBUF[0].CMDBYTE1 == 0); // This command can start/stop the stream
// Stop stream
if (m_DICMDBUF[0].CMDBYTE1 == 1)
{
AudioPos = 0;
LoopStart = 0;
LoopLength = 0;
CurrentStart = 0;
CurrentLength = 0;
}
WARN_LOG(DVDINTERFACE, "(Audio) Stream subcmd = %08x offset = %08x length=%08x",
m_DICMDBUF[0].Hex, m_DICMDBUF[1].Hex << 2, m_DICMDBUF[2].Hex);
}
break;
// Request Audio Status (Immediate)
case 0xE2:
m_DIIMMBUF.Hex = g_bStream ? 1 : 0;
//WARN_LOG(DVDINTERFACE, "(Audio): Request Audio status %s", g_bStream? "on":"off");
{
switch (m_DICMDBUF[0].CMDBYTE1)
{
case 0x00: // Returns streaming status
m_DIIMMBUF.Hex = (AudioPos == 0) ? 0 : 1;
break;
case 0x01: // Returns the current offset
if (g_bStream)
m_DIIMMBUF.Hex = (AudioPos - CurrentStart) >> 2;
else
m_DIIMMBUF.Hex = 0;
break;
case 0x02: // Returns the start offset
if (g_bStream)
m_DIIMMBUF.Hex = CurrentStart >> 2;
else
m_DIIMMBUF.Hex = 0;
break;
case 0x03: // Returns the total length
if (g_bStream)
m_DIIMMBUF.Hex = CurrentLength;
else
m_DIIMMBUF.Hex = 0;
break;
default:
WARN_LOG(DVDINTERFACE, "(Audio): Subcommand: %02x Request Audio status %s", m_DICMDBUF[0].CMDBYTE1, g_bStream? "on":"off");
break;
}
}
break;
case DVDLowStopMotor:

View File

@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "MathUtil.h"
#include "CommonPaths.h"
#include "VolumeDirectory.h"
#include "FileBlob.h"
@ -23,17 +24,6 @@
namespace DiscIO
{
static const u8 ENTRY_SIZE = 0x0c;
static const u8 FILE_ENTRY = 0;
static const u8 DIRECTORY_ENTRY = 1;
static const u64 DISKHEADER_ADDRESS = 0;
static const u64 DISKHEADERINFO_ADDRESS = 0x440;
static const u64 APPLOADER_ADDRESS = 0x2440;
static const u32 MAX_NAME_LENGTH = 0x3df;
// relocatable
static u64 FST_ADDRESS = 0x440;
static u64 DOL_ADDRESS = 0;
CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii,
const std::string& _rApploader, const std::string& _rDOL)
: m_totalNameSize(0)
@ -44,6 +34,8 @@ CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii,
, m_apploader(NULL)
, m_DOLSize(0)
, m_DOL(NULL)
, FST_ADDRESS(0)
, DOL_ADDRESS(0)
{
m_rootDirectory = ExtractDirectoryName(_rDirectory);
@ -321,7 +313,7 @@ bool CVolumeDirectory::SetApploader(const std::string& _rApploader)
copy(data.begin(), data.end(), m_apploader);
// 32byte aligned (plus 0x20 padding)
DOL_ADDRESS = (APPLOADER_ADDRESS + m_apploaderSize + 0x20 + 31) & ~31ULL;
DOL_ADDRESS = ROUND_UP(APPLOADER_ADDRESS + m_apploaderSize + 0x20, 0x20ull);
return true;
}
else
@ -347,7 +339,7 @@ void CVolumeDirectory::SetDOL(const std::string& _rDOL)
Write32((u32)(DOL_ADDRESS >> m_addressShift), 0x0420, m_diskHeader);
// 32byte aligned (plus 0x20 padding)
FST_ADDRESS = (DOL_ADDRESS + m_DOLSize + 0x20 + 31) & ~31ULL;
FST_ADDRESS = ROUND_UP(DOL_ADDRESS + m_DOLSize + 0x20, 0x20ull);
}
}
@ -367,8 +359,12 @@ void CVolumeDirectory::BuildFST()
m_fstSize = m_fstNameOffset + m_totalNameSize;
m_FSTData = new u8[(u32)m_fstSize];
// if FST hasn't been assigned (ie no apploader/dol setup), set to default
if (FST_ADDRESS == 0)
FST_ADDRESS = APPLOADER_ADDRESS + 0x2000;
// 4 byte aligned start of data on disk
m_dataStartAddress = (FST_ADDRESS + m_fstSize + 3) & ~3;
m_dataStartAddress = ROUND_UP(FST_ADDRESS + m_fstSize, 0x8000ull);
u64 curDataAddress = m_dataStartAddress;
u32 fstOffset = 0; // offset within FST data
@ -490,7 +486,7 @@ void CVolumeDirectory::WriteEntry(const File::FSTEntry& entry, u32& fstOffset, u
m_virtualDisk.insert(make_pair(dataOffset, entry.physicalName));
// 4 byte aligned
dataOffset = (dataOffset + entry.size + 3) & ~3ULL;
dataOffset = ROUND_UP(dataOffset + entry.size, 0x8000ull);
}
}

View File

@ -141,6 +141,16 @@ private:
u64 m_DOLSize;
u8* m_DOL;
static const u8 ENTRY_SIZE = 0x0c;
static const u8 FILE_ENTRY = 0;
static const u8 DIRECTORY_ENTRY = 1;
static const u64 DISKHEADER_ADDRESS = 0;
static const u64 DISKHEADERINFO_ADDRESS = 0x440;
static const u64 APPLOADER_ADDRESS = 0x2440;
static const u32 MAX_NAME_LENGTH = 0x3df;
u64 FST_ADDRESS;
u64 DOL_ADDRESS;
};
} // namespace

View File

@ -116,7 +116,6 @@ EVT_CHECKBOX(ID_NTSCJ, CConfigMain::CoreSettingsChanged)
EVT_RADIOBOX(ID_DSPENGINE, CConfigMain::AudioSettingsChanged)
EVT_CHECKBOX(ID_ENABLE_DTK_MUSIC, CConfigMain::AudioSettingsChanged)
EVT_CHECKBOX(ID_DSPTHREAD, CConfigMain::AudioSettingsChanged)
EVT_CHECKBOX(ID_ENABLE_THROTTLE, CConfigMain::AudioSettingsChanged)
EVT_CHECKBOX(ID_DUMP_AUDIO, CConfigMain::AudioSettingsChanged)
@ -359,7 +358,6 @@ void CConfigMain::InitializeGUIValues()
VolumeSlider->Enable(SupportsVolumeChanges(ac_Config.sBackend));
VolumeSlider->SetValue(ac_Config.m_Volume);
VolumeText->SetLabel(wxString::Format(wxT("%d %%"), ac_Config.m_Volume));
EnableDTKMusic->SetValue(ac_Config.m_EnableDTKMusic ? true : false);
DSPThread->SetValue(startup_params.bDSPThread);
DumpAudio->SetValue(ac_Config.m_DumpAudio ? true : false);
FrequencySelection->SetSelection(
@ -502,7 +500,6 @@ void CConfigMain::InitializeGUITooltips()
InterfaceLang->SetToolTip(_("Change the language of the user interface.\nRequires restart."));
// Audio tooltips
EnableDTKMusic->SetToolTip(_("This is used to play music tracks, like BGM."));
DSPThread->SetToolTip(_("Run DSP LLE on a dedicated thread (not recommended)."));
FrequencySelection->SetToolTip(_("Changing this will have no effect while the emulator is running!"));
BackendSelection->SetToolTip(_("Changing this will have no effect while the emulator is running!"));
@ -602,8 +599,6 @@ void CConfigMain::CreateGUIControls()
// Audio page
DSPEngine = new wxRadioBox(AudioPage, ID_DSPENGINE, _("DSP Emulator Engine"),
wxDefaultPosition, wxDefaultSize, arrayStringFor_DSPEngine, 0, wxRA_SPECIFY_ROWS);
EnableDTKMusic = new wxCheckBox(AudioPage, ID_ENABLE_DTK_MUSIC, _("Enable DTK Music"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
DSPThread = new wxCheckBox(AudioPage, ID_DSPTHREAD, _("DSP LLE on Thread"));
DumpAudio = new wxCheckBox(AudioPage, ID_DUMP_AUDIO, _("Dump Audio"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
@ -620,7 +615,6 @@ void CConfigMain::CreateGUIControls()
// Create sizer and add items to dialog
wxStaticBoxSizer *sbAudioSettings = new wxStaticBoxSizer(wxVERTICAL, AudioPage, _("Sound Settings"));
sbAudioSettings->Add(DSPEngine, 0, wxALL | wxEXPAND, 5);
sbAudioSettings->Add(EnableDTKMusic, 0, wxALL, 5);
sbAudioSettings->Add(DSPThread, 0, wxALL, 5);
sbAudioSettings->Add(DumpAudio, 0, wxALL, 5);
@ -918,7 +912,6 @@ void CConfigMain::AudioSettingsChanged(wxCommandEvent& event)
break;
default:
ac_Config.m_EnableDTKMusic = EnableDTKMusic->GetValue();
ac_Config.m_DumpAudio = DumpAudio->GetValue();
long int frequency;

View File

@ -77,7 +77,6 @@ private:
// Audio Settings
ID_DSPENGINE,
ID_ENABLE_HLE_AUDIO,
ID_ENABLE_DTK_MUSIC,
ID_ENABLE_THROTTLE,
ID_DUMP_AUDIO,
ID_FREQUENCY,
@ -156,7 +155,6 @@ private:
wxRadioBox* DSPEngine;
wxSlider* VolumeSlider;
wxStaticText* VolumeText;
wxCheckBox* EnableDTKMusic;
wxCheckBox* DumpAudio;
wxArrayString wxArrayBackends;
wxChoice* BackendSelection;