mirror of
https://github.com/libretro/Play-.git
synced 2025-02-04 07:56:10 +00:00
Add basic support for SPU sound input.
This commit is contained in:
parent
8532219da6
commit
9445424dc5
@ -172,6 +172,10 @@ void CSpuBase::Reset()
|
||||
m_reader[i].Reset();
|
||||
m_reader[i].SetMemory(m_ram, m_ramSize);
|
||||
}
|
||||
|
||||
m_blockReader.Reset();
|
||||
m_soundInputDataAddr = (m_spuNumber == 0) ? SOUND_INPUT_DATA_CORE0_BASE : SOUND_INPUT_DATA_CORE1_BASE;
|
||||
m_blockWritePtr = 0;
|
||||
}
|
||||
|
||||
void CSpuBase::LoadState(Framework::CZipArchiveReader& archive)
|
||||
@ -458,29 +462,50 @@ uint32 CSpuBase::ReceiveDma(uint8* buffer, uint32 blockSize, uint32 blockAmount)
|
||||
CLog::GetInstance().Print(LOG_NAME, "Receiving DMA transfer to 0x%0.8X. Size = 0x%0.8X bytes.\r\n",
|
||||
m_transferAddr, blockSize * blockAmount);
|
||||
#endif
|
||||
if(m_transferMode != TRANSFER_MODE_VOICE)
|
||||
if(m_transferMode == TRANSFER_MODE_VOICE)
|
||||
{
|
||||
//CORE0/1 block modes should have transferAddr == 0
|
||||
blockAmount = 1;
|
||||
if((m_ctrl & CONTROL_DMA) == CONTROL_DMA_READ)
|
||||
{
|
||||
//DMA reads need to be throttled to allow FFX IopSoundDriver to properly synchronize itself
|
||||
blockAmount = std::min<uint32>(blockAmount, 0x10);
|
||||
return blockAmount;
|
||||
}
|
||||
unsigned int blocksTransfered = 0;
|
||||
for(unsigned int i = 0; i < blockAmount; i++)
|
||||
{
|
||||
uint32 copySize = std::min<uint32>(m_ramSize - m_transferAddr, blockSize);
|
||||
memcpy(m_ram + m_transferAddr, buffer, copySize);
|
||||
m_transferAddr += blockSize;
|
||||
m_transferAddr &= m_ramSize - 1;
|
||||
buffer += blockSize;
|
||||
blocksTransfered++;
|
||||
}
|
||||
return blocksTransfered;
|
||||
}
|
||||
else if(
|
||||
(m_transferMode == TRANSFER_MODE_BLOCK_CORE0IN) ||
|
||||
(m_transferMode == TRANSFER_MODE_BLOCK_CORE1IN)
|
||||
)
|
||||
{
|
||||
assert(m_transferAddr == 0);
|
||||
assert((m_spuNumber == 0) || !(m_transferMode == TRANSFER_MODE_BLOCK_CORE0IN));
|
||||
assert((m_spuNumber == 1) || !(m_transferMode == TRANSFER_MODE_BLOCK_CORE1IN));
|
||||
assert(m_blockWritePtr <= SOUND_INPUT_DATA_SIZE);
|
||||
|
||||
uint32 availableBytes = SOUND_INPUT_DATA_SIZE - m_blockWritePtr;
|
||||
uint32 availableBlocks = availableBytes / blockSize;
|
||||
blockAmount = std::min(blockAmount, availableBlocks);
|
||||
|
||||
uint32 dstAddr = m_soundInputDataAddr + m_blockWritePtr;
|
||||
memcpy(m_ram + dstAddr, buffer, blockAmount * blockSize);
|
||||
m_blockWritePtr += blockAmount * blockSize;
|
||||
|
||||
return blockAmount;
|
||||
}
|
||||
if((m_ctrl & CONTROL_DMA) == CONTROL_DMA_READ)
|
||||
else
|
||||
{
|
||||
//DMA reads need to be throttled to allow FFX IopSoundDriver to properly synchronize itself
|
||||
blockAmount = std::min<uint32>(blockAmount, 0x10);
|
||||
return blockAmount;
|
||||
return 1;
|
||||
}
|
||||
unsigned int blocksTransfered = 0;
|
||||
for(unsigned int i = 0; i < blockAmount; i++)
|
||||
{
|
||||
uint32 copySize = std::min<uint32>(m_ramSize - m_transferAddr, blockSize);
|
||||
memcpy(m_ram + m_transferAddr, buffer, copySize);
|
||||
m_transferAddr += blockSize;
|
||||
m_transferAddr &= m_ramSize - 1;
|
||||
buffer += blockSize;
|
||||
blocksTransfered++;
|
||||
}
|
||||
return blocksTransfered;
|
||||
}
|
||||
|
||||
void CSpuBase::WriteWord(uint16 value)
|
||||
@ -612,6 +637,24 @@ void CSpuBase::Render(int16* samples, unsigned int sampleCount, unsigned int sam
|
||||
MixSamples(inputSample, adjustedRightVolume, reverbSample + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_blockReader.CanReadSamples() && (m_blockWritePtr == SOUND_INPUT_DATA_SIZE))
|
||||
{
|
||||
//We're ready to consume some data
|
||||
m_blockReader.FillBlock(m_ram + m_soundInputDataAddr);
|
||||
m_blockWritePtr = 0;
|
||||
}
|
||||
|
||||
if(m_blockReader.CanReadSamples())
|
||||
{
|
||||
int16 sampleL = 0;
|
||||
int16 sampleR = 0;
|
||||
m_blockReader.GetSamples(sampleL, sampleR, sampleRate);
|
||||
|
||||
MixSamples(sampleL, 0x3FFF, samples + 0);
|
||||
MixSamples(sampleR, 0x3FFF, samples + 1);
|
||||
}
|
||||
|
||||
//Update reverb
|
||||
if(updateReverb)
|
||||
{
|
||||
@ -1123,3 +1166,37 @@ void CSpuBase::CSampleReader::ClearDidChangeRepeat()
|
||||
{
|
||||
m_didChangeRepeat = false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// CBlockSampleReader
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
void CSpuBase::CBlockSampleReader::Reset()
|
||||
{
|
||||
m_srcSampleIdx = SOUND_INPUT_DATA_SAMPLES * TIME_SCALE;
|
||||
}
|
||||
|
||||
bool CSpuBase::CBlockSampleReader::CanReadSamples() const
|
||||
{
|
||||
uint32 sampleIdx = (m_srcSampleIdx / TIME_SCALE);
|
||||
return (sampleIdx < SOUND_INPUT_DATA_SAMPLES);
|
||||
}
|
||||
|
||||
void CSpuBase::CBlockSampleReader::FillBlock(const uint8* block)
|
||||
{
|
||||
memcpy(m_blockBuffer, block, SOUND_INPUT_DATA_SIZE);
|
||||
m_srcSampleIdx = 0;
|
||||
}
|
||||
|
||||
void CSpuBase::CBlockSampleReader::GetSamples(int16& sampleL, int16& sampleR, unsigned int dstSamplingRate)
|
||||
{
|
||||
uint32 srcSampleIdx = m_srcSampleIdx / TIME_SCALE;
|
||||
int32 srcSampleAlpha = m_srcSampleIdx % TIME_SCALE;
|
||||
assert(srcSampleIdx < SOUND_INPUT_DATA_SAMPLES);
|
||||
|
||||
auto inputSamples = reinterpret_cast<const int16*>(m_blockBuffer);
|
||||
sampleL = inputSamples[0x000 + srcSampleIdx];
|
||||
sampleR = inputSamples[0x100 + srcSampleIdx];
|
||||
|
||||
m_srcSampleIdx += (SRC_SAMPLING_RATE * TIME_SCALE) / dstSamplingRate;
|
||||
}
|
||||
|
@ -219,6 +219,14 @@ namespace Iop
|
||||
static bool g_reverbParamIsAddress[REVERB_PARAM_COUNT];
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
SOUND_INPUT_DATA_CORE0_BASE = 0x2000,
|
||||
SOUND_INPUT_DATA_CORE1_BASE = 0x2400,
|
||||
SOUND_INPUT_DATA_SIZE = 0x400,
|
||||
SOUND_INPUT_DATA_SAMPLES = (SOUND_INPUT_DATA_SIZE / 4),
|
||||
};
|
||||
|
||||
class CSampleReader
|
||||
{
|
||||
public:
|
||||
@ -273,6 +281,25 @@ namespace Iop
|
||||
bool m_didChangeRepeat;
|
||||
};
|
||||
|
||||
class CBlockSampleReader
|
||||
{
|
||||
public:
|
||||
void Reset();
|
||||
bool CanReadSamples() const;
|
||||
|
||||
void FillBlock(const uint8*);
|
||||
void GetSamples(int16&, int16&, unsigned int);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
SRC_SAMPLING_RATE = 48000,
|
||||
};
|
||||
|
||||
uint32 m_srcSampleIdx = 0;
|
||||
uint8 m_blockBuffer[SOUND_INPUT_DATA_SIZE];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_ADSR_VOLUME = 0x7FFFFFFF,
|
||||
@ -312,5 +339,9 @@ namespace Iop
|
||||
uint32 m_adsrLogTable[160];
|
||||
bool m_reverbEnabled;
|
||||
float m_volumeAdjust;
|
||||
|
||||
CBlockSampleReader m_blockReader;
|
||||
uint32 m_soundInputDataAddr = 0;
|
||||
uint32 m_blockWritePtr = 0;
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user