mirror of
https://github.com/DaedalusX64/daedalus.git
synced 2025-04-02 10:21:48 -04:00
341 lines
No EOL
7.5 KiB
C++
341 lines
No EOL
7.5 KiB
C++
/*
|
|
Copyright (C) 2003 Azimer
|
|
Copyright (C) 2001,2006 StrmnNrmn
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
//
|
|
// N.B. This source code is derived from Azimer's Audio plugin (v0.55?)
|
|
// and modified by StrmnNrmn to work with Daedalus PSP. Thanks Azimer!
|
|
// Drop me a line if you get chance :)
|
|
//
|
|
|
|
#include "BuildOptions.h"
|
|
#include "Base/Types.h"
|
|
#include <stdio.h>
|
|
#include <new>
|
|
|
|
#include <pspkernel.h>
|
|
#include <pspaudiolib.h>
|
|
#include <pspaudio.h>
|
|
|
|
#include "Config/ConfigOptions.h"
|
|
#include "Core/CPU.h"
|
|
#include "Core/Interrupt.h"
|
|
#include "Core/Memory.h"
|
|
#include "Core/ROM.h"
|
|
#include "Core/RSP_HLE.h"
|
|
#include "Debug/DBGConsole.h"
|
|
#include "HLEAudio/HLEAudioInternal.h"
|
|
#include "HLEAudio/AudioBuffer.h"
|
|
#include "HLEAudio/AudioPlugin.h"
|
|
// #include "SysPSP/Utility/JobManager.h"
|
|
#include "SysPSP/Utility/CacheUtil.h"
|
|
// #include "SysPSP/Utility/JobManager.h"
|
|
#include "Core/FramerateLimiter.h"
|
|
#include "System/Thread.h"
|
|
|
|
#ifdef DAEDALUS_PSP_USE_ME
|
|
|
|
#include "SysPSP/PRX/MediaEngine/me.h"
|
|
#include "SysPSP/Utility/ModulePSP.h"
|
|
|
|
bool gLoadedMediaEnginePRX {false};
|
|
|
|
volatile me_struct *mei;
|
|
|
|
bool InitialiseMediaEngine()
|
|
{
|
|
if ( gLoadedMediaEnginePRX == false)
|
|
{
|
|
if( CModule::Load("Plugins/mediaengine.prx") < 0 ) return false;
|
|
|
|
mei = (volatile struct me_struct *)malloc_64(sizeof(struct me_struct));
|
|
mei = (volatile struct me_struct *)(make_uncached_ptr(mei));
|
|
sceKernelDcacheWritebackInvalidateAll();
|
|
|
|
if (InitME(mei) == 0)
|
|
{
|
|
gLoadedMediaEnginePRX = true;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DAEDALUS_DEBUG_CONSOLE
|
|
printf(" Couldn't initialize MediaEngine Instance\n");
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("Media Engine already Initialised\n");
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#define RSP_AUDIO_INTR_CYCLES 1
|
|
extern u32 gSoundSync;
|
|
|
|
static const u32 kOutputFrequency = 44100;
|
|
static const u32 MAX_OUTPUT_FREQUENCY = kOutputFrequency * 4;
|
|
|
|
|
|
static bool audio_open = false;
|
|
|
|
|
|
// Large kAudioBufferSize creates huge delay on sound //Corn
|
|
static const u32 kAudioBufferSize = 1024 * 2; // OSX uses a circular buffer length, 1024 * 1024
|
|
|
|
|
|
class AudioPluginPSP : public CAudioPlugin
|
|
{
|
|
public:
|
|
|
|
AudioPluginPSP();
|
|
virtual ~AudioPluginPSP();
|
|
virtual bool StartEmulation();
|
|
virtual void StopEmulation();
|
|
|
|
virtual void DacrateChanged( int system_type );
|
|
virtual void LenChanged();
|
|
virtual u32 ReadLength() {return 0;}
|
|
virtual EProcessResult ProcessAList();
|
|
|
|
//virtual void SetFrequency(u32 frequency);
|
|
virtual void AddBuffer( u8 * start, u32 length);
|
|
virtual void FillBuffer( Sample * buffer, u32 num_samples);
|
|
|
|
virtual void StopAudio();
|
|
virtual void StartAudio();
|
|
|
|
public:
|
|
CAudioBuffer * mAudioBufferUncached;
|
|
|
|
private:
|
|
CAudioBuffer * mAudioBuffer;
|
|
bool mKeepRunning;
|
|
bool mExitAudioThread;
|
|
u32 mFrequency;
|
|
s32 mAudioThread;
|
|
s32 mSemaphore;
|
|
// u32 mBufferLenMs;
|
|
};
|
|
|
|
static AudioPluginPSP * ac;
|
|
|
|
void AudioPluginPSP::FillBuffer(Sample * buffer, u32 num_samples)
|
|
{
|
|
sceKernelWaitSema( mSemaphore, 1, nullptr );
|
|
|
|
mAudioBufferUncached->Drain( buffer, num_samples );
|
|
|
|
sceKernelSignalSema( mSemaphore, 1 );
|
|
}
|
|
|
|
|
|
EAudioPluginMode gAudioPluginEnabled( APM_DISABLED );
|
|
|
|
|
|
AudioPluginPSP::AudioPluginPSP()
|
|
:mKeepRunning (false)
|
|
//: mAudioBuffer( kAudioBufferSize )
|
|
, mFrequency( 44100 )
|
|
, mSemaphore( sceKernelCreateSema( "AudioPluginPSP", 0, 1, 1, nullptr ) )
|
|
//, mAudioThread ( kInvalidThreadHandle )
|
|
//, mKeepRunning( false )
|
|
//, mBufferLenMs ( 0 )
|
|
{
|
|
// Allocate audio buffer with malloc_64 to avoid cached/uncached aliasing
|
|
void * mem = malloc_64( sizeof( CAudioBuffer ) );
|
|
mAudioBuffer = new( mem ) CAudioBuffer( kAudioBufferSize );
|
|
mAudioBufferUncached = (CAudioBuffer*)make_uncached_ptr(mem);
|
|
// Ideally we could just invalidate this range?
|
|
dcache_wbinv_range_unaligned( mAudioBuffer, mAudioBuffer+sizeof( CAudioBuffer ) );
|
|
|
|
#ifdef DAEDALUS_PSP_USE_ME
|
|
InitialiseMediaEngine();
|
|
#endif
|
|
}
|
|
|
|
AudioPluginPSP::~AudioPluginPSP( )
|
|
{
|
|
mAudioBuffer->~CAudioBuffer();
|
|
free(mAudioBuffer);
|
|
sceKernelDeleteSema(mSemaphore);
|
|
pspAudioEnd();
|
|
}
|
|
|
|
bool AudioPluginPSP::StartEmulation()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
void AudioPluginPSP::StopEmulation()
|
|
{
|
|
Audio_Reset();
|
|
StopAudio();
|
|
sceKernelDeleteSema(mSemaphore);
|
|
pspAudioEndPre();
|
|
sceKernelDelayThread(100000);
|
|
pspAudioEnd();
|
|
|
|
|
|
}
|
|
|
|
void AudioPluginPSP::DacrateChanged( int system_type )
|
|
{
|
|
u32 clock = (system_type == ST_NTSC) ? VI_NTSC_CLOCK : VI_PAL_CLOCK;
|
|
u32 dacrate = Memory_AI_GetRegister(AI_DACRATE_REG);
|
|
u32 frequency = clock / (dacrate + 1);
|
|
|
|
#ifdef DAEDALUS_DEBUG_CONSOLE
|
|
DBGConsole_Msg(0, "Audio frequency: %d", frequency);
|
|
#endif
|
|
mFrequency = frequency;
|
|
}
|
|
|
|
|
|
void AudioPluginPSP::LenChanged()
|
|
{
|
|
if( gAudioPluginEnabled > APM_DISABLED )
|
|
{
|
|
u32 address = Memory_AI_GetRegister(AI_DRAM_ADDR_REG) & 0xFFFFFF;
|
|
u32 length = Memory_AI_GetRegister(AI_LEN_REG);
|
|
|
|
AddBuffer( g_pu8RamBase + address, length );
|
|
}
|
|
else
|
|
{
|
|
StopAudio();
|
|
}
|
|
}
|
|
|
|
|
|
EProcessResult AudioPluginPSP::ProcessAList()
|
|
{
|
|
Memory_SP_SetRegisterBits(SP_STATUS_REG, SP_STATUS_HALT);
|
|
|
|
EProcessResult result = PR_NOT_STARTED;
|
|
|
|
switch( gAudioPluginEnabled )
|
|
{
|
|
case APM_DISABLED:
|
|
result = PR_COMPLETED;
|
|
break;
|
|
case APM_ENABLED_ASYNC:
|
|
{
|
|
sceKernelDcacheWritebackInvalidateAll();
|
|
if(BeginME( mei, (int)&Audio_Ucode, (int)NULL, -1, NULL, -1, NULL) < 0){
|
|
Audio_Ucode();
|
|
result = PR_COMPLETED;
|
|
break;
|
|
}
|
|
}
|
|
result = PR_COMPLETED;
|
|
break;
|
|
case APM_ENABLED_SYNC:
|
|
Audio_Ucode();
|
|
result = PR_COMPLETED;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void audioCallback( void * buf, unsigned int length, void * userdata )
|
|
{
|
|
AudioPluginPSP * ac( reinterpret_cast< AudioPluginPSP * >( userdata ) );
|
|
|
|
ac->FillBuffer( reinterpret_cast< Sample * >( buf ), length );
|
|
}
|
|
|
|
|
|
void AudioPluginPSP::StartAudio()
|
|
{
|
|
if (mKeepRunning)
|
|
return;
|
|
|
|
mKeepRunning = true;
|
|
|
|
ac = this;
|
|
|
|
|
|
pspAudioInit();
|
|
pspAudioSetChannelCallback( 0, audioCallback, this );
|
|
|
|
// Everything OK
|
|
audio_open = true;
|
|
}
|
|
|
|
void AudioPluginPSP::AddBuffer( u8 *start, u32 length )
|
|
{
|
|
if (length == 0)
|
|
return;
|
|
|
|
if (!mKeepRunning)
|
|
StartAudio();
|
|
|
|
u32 num_samples = length / sizeof( Sample );
|
|
|
|
switch( gAudioPluginEnabled )
|
|
{
|
|
case APM_DISABLED:
|
|
break;
|
|
|
|
case APM_ENABLED_ASYNC:
|
|
{
|
|
|
|
mAudioBufferUncached->AddSamples( reinterpret_cast< const Sample * >( start ), num_samples, mFrequency, kOutputFrequency );
|
|
|
|
}
|
|
break;
|
|
|
|
case APM_ENABLED_SYNC:
|
|
{
|
|
mAudioBufferUncached->AddSamples( reinterpret_cast< const Sample * >( start ), num_samples, mFrequency, kOutputFrequency );
|
|
}
|
|
break;
|
|
}
|
|
|
|
/*
|
|
u32 remaining_samples = mAudioBuffer.GetNumBufferedSamples();
|
|
mBufferLenMs = (1000 * remaining_samples) / kOutputFrequency);
|
|
float ms = (float) num_samples * 1000.f / (float)mFrequency;
|
|
#ifdef DAEDALUS_DEBUG_CONSOLE
|
|
DPF_AUDIO("Queuing %d samples @%dHz - %.2fms - bufferlen now %d\n", num_samples, mFrequency, ms, mBufferLenMs);
|
|
#endif
|
|
*/
|
|
}
|
|
|
|
void AudioPluginPSP::StopAudio()
|
|
{
|
|
if (!mKeepRunning)
|
|
return;
|
|
|
|
mKeepRunning = false;
|
|
|
|
audio_open = false;
|
|
}
|
|
|
|
std::unique_ptr<CAudioPlugin> CreateAudioPlugin()
|
|
{
|
|
return std::make_unique<AudioPluginPSP>();
|
|
} |