2018-11-16 19:36:49 -08:00
|
|
|
using Ryujinx.HLE.HOS.Ipc;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Aud
|
|
|
|
{
|
|
|
|
class IHardwareOpusDecoderManager : IpcService
|
|
|
|
{
|
2018-12-04 16:52:39 -08:00
|
|
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
2018-11-16 19:36:49 -08:00
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
2018-11-16 19:36:49 -08:00
|
|
|
|
|
|
|
public IHardwareOpusDecoderManager()
|
|
|
|
{
|
2018-12-04 16:52:39 -08:00
|
|
|
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
2018-11-16 19:36:49 -08:00
|
|
|
{
|
|
|
|
{ 0, Initialize },
|
|
|
|
{ 1, GetWorkBufferSize }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
public long Initialize(ServiceCtx Context)
|
2018-11-16 19:36:49 -08:00
|
|
|
{
|
2018-12-04 16:52:39 -08:00
|
|
|
int SampleRate = Context.RequestData.ReadInt32();
|
|
|
|
int ChannelsCount = Context.RequestData.ReadInt32();
|
2018-11-16 19:36:49 -08:00
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
MakeObject(Context, new IHardwareOpusDecoder(SampleRate, ChannelsCount));
|
2018-11-16 19:36:49 -08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
public long GetWorkBufferSize(ServiceCtx Context)
|
2018-11-16 19:36:49 -08:00
|
|
|
{
|
|
|
|
//Note: The sample rate is ignored because it is fixed to 48KHz.
|
2018-12-04 16:52:39 -08:00
|
|
|
int SampleRate = Context.RequestData.ReadInt32();
|
|
|
|
int ChannelsCount = Context.RequestData.ReadInt32();
|
2018-11-16 19:36:49 -08:00
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
Context.ResponseData.Write(GetOpusDecoderSize(ChannelsCount));
|
2018-11-16 19:36:49 -08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
private static int GetOpusDecoderSize(int ChannelsCount)
|
2018-11-16 19:36:49 -08:00
|
|
|
{
|
2018-12-04 16:52:39 -08:00
|
|
|
const int SilkDecoderSize = 0x2198;
|
2018-11-16 19:36:49 -08:00
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
if (ChannelsCount < 1 || ChannelsCount > 2)
|
2018-11-16 19:36:49 -08:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
int CeltDecoderSize = GetCeltDecoderSize(ChannelsCount);
|
2018-11-16 19:36:49 -08:00
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
int OpusDecoderSize = (ChannelsCount * 0x800 + 0x4807) & -0x800 | 0x50;
|
2018-11-16 19:36:49 -08:00
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
return OpusDecoderSize + SilkDecoderSize + CeltDecoderSize;
|
2018-11-16 19:36:49 -08:00
|
|
|
}
|
|
|
|
|
2018-12-04 16:52:39 -08:00
|
|
|
private static int GetCeltDecoderSize(int ChannelsCount)
|
2018-11-16 19:36:49 -08:00
|
|
|
{
|
2018-12-04 16:52:39 -08:00
|
|
|
const int DecodeBufferSize = 0x2030;
|
|
|
|
const int CeltDecoderSize = 0x58;
|
|
|
|
const int CeltSigSize = 0x4;
|
|
|
|
const int Overlap = 120;
|
|
|
|
const int EBandsCount = 21;
|
|
|
|
|
|
|
|
return (DecodeBufferSize + Overlap * 4) * ChannelsCount +
|
|
|
|
EBandsCount * 16 +
|
|
|
|
CeltDecoderSize +
|
|
|
|
CeltSigSize;
|
2018-11-16 19:36:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|