Adjust naming conventions and general refactoring in HLE Project (#490)
* Rename enum fields * Naming conventions * Remove unneeded ".this" * Remove unneeded semicolons * Remove unused Usings * Don't use var * Remove unneeded enum underlying types * Explicitly label class visibility * Remove unneeded @ prefixes * Remove unneeded commas * Remove unneeded if expressions * Method doesn't use unsafe code * Remove unneeded casts * Initialized objects don't need an empty constructor * Remove settings from DotSettings * Revert "Explicitly label class visibility" This reverts commit ad5eb5787cc5b27a4631cd46ef5f551c4ae95e51. * Small changes * Revert external enum renaming * Changes from feedback * Remove unneeded property setters
This commit is contained in:
parent
c86aacde76
commit
85dbb9559a
299 changed files with 12268 additions and 12276 deletions
|
@ -9,19 +9,19 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioOut
|
|||
{
|
||||
class IAudioOut : IpcService, IDisposable
|
||||
{
|
||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||
private Dictionary<int, ServiceProcessRequest> _commands;
|
||||
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
|
||||
|
||||
private IAalOutput AudioOut;
|
||||
private IAalOutput _audioOut;
|
||||
|
||||
private KEvent ReleaseEvent;
|
||||
private KEvent _releaseEvent;
|
||||
|
||||
private int Track;
|
||||
private int _track;
|
||||
|
||||
public IAudioOut(IAalOutput AudioOut, KEvent ReleaseEvent, int Track)
|
||||
public IAudioOut(IAalOutput audioOut, KEvent releaseEvent, int track)
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
_commands = new Dictionary<int, ServiceProcessRequest>
|
||||
{
|
||||
{ 0, GetAudioOutState },
|
||||
{ 1, StartAudioOut },
|
||||
|
@ -34,116 +34,116 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioOut
|
|||
{ 8, GetReleasedAudioOutBufferAuto }
|
||||
};
|
||||
|
||||
this.AudioOut = AudioOut;
|
||||
this.ReleaseEvent = ReleaseEvent;
|
||||
this.Track = Track;
|
||||
_audioOut = audioOut;
|
||||
_releaseEvent = releaseEvent;
|
||||
_track = track;
|
||||
}
|
||||
|
||||
public long GetAudioOutState(ServiceCtx Context)
|
||||
public long GetAudioOutState(ServiceCtx context)
|
||||
{
|
||||
Context.ResponseData.Write((int)AudioOut.GetState(Track));
|
||||
context.ResponseData.Write((int)_audioOut.GetState(_track));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long StartAudioOut(ServiceCtx Context)
|
||||
public long StartAudioOut(ServiceCtx context)
|
||||
{
|
||||
AudioOut.Start(Track);
|
||||
_audioOut.Start(_track);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long StopAudioOut(ServiceCtx Context)
|
||||
public long StopAudioOut(ServiceCtx context)
|
||||
{
|
||||
AudioOut.Stop(Track);
|
||||
_audioOut.Stop(_track);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long AppendAudioOutBuffer(ServiceCtx Context)
|
||||
public long AppendAudioOutBuffer(ServiceCtx context)
|
||||
{
|
||||
return AppendAudioOutBufferImpl(Context, Context.Request.SendBuff[0].Position);
|
||||
return AppendAudioOutBufferImpl(context, context.Request.SendBuff[0].Position);
|
||||
}
|
||||
|
||||
public long RegisterBufferEvent(ServiceCtx Context)
|
||||
public long RegisterBufferEvent(ServiceCtx context)
|
||||
{
|
||||
if (Context.Process.HandleTable.GenerateHandle(ReleaseEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||
if (context.Process.HandleTable.GenerateHandle(_releaseEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
||||
{
|
||||
throw new InvalidOperationException("Out of handles!");
|
||||
}
|
||||
|
||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetReleasedAudioOutBuffer(ServiceCtx Context)
|
||||
public long GetReleasedAudioOutBuffer(ServiceCtx context)
|
||||
{
|
||||
long Position = Context.Request.ReceiveBuff[0].Position;
|
||||
long Size = Context.Request.ReceiveBuff[0].Size;
|
||||
long position = context.Request.ReceiveBuff[0].Position;
|
||||
long size = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
return GetReleasedAudioOutBufferImpl(Context, Position, Size);
|
||||
return GetReleasedAudioOutBufferImpl(context, position, size);
|
||||
}
|
||||
|
||||
public long ContainsAudioOutBuffer(ServiceCtx Context)
|
||||
public long ContainsAudioOutBuffer(ServiceCtx context)
|
||||
{
|
||||
long Tag = Context.RequestData.ReadInt64();
|
||||
long tag = context.RequestData.ReadInt64();
|
||||
|
||||
Context.ResponseData.Write(AudioOut.ContainsBuffer(Track, Tag) ? 1 : 0);
|
||||
context.ResponseData.Write(_audioOut.ContainsBuffer(_track, tag) ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long AppendAudioOutBufferAuto(ServiceCtx Context)
|
||||
public long AppendAudioOutBufferAuto(ServiceCtx context)
|
||||
{
|
||||
(long Position, long Size) = Context.Request.GetBufferType0x21();
|
||||
(long position, long size) = context.Request.GetBufferType0x21();
|
||||
|
||||
return AppendAudioOutBufferImpl(Context, Position);
|
||||
return AppendAudioOutBufferImpl(context, position);
|
||||
}
|
||||
|
||||
public long AppendAudioOutBufferImpl(ServiceCtx Context, long Position)
|
||||
public long AppendAudioOutBufferImpl(ServiceCtx context, long position)
|
||||
{
|
||||
long Tag = Context.RequestData.ReadInt64();
|
||||
long tag = context.RequestData.ReadInt64();
|
||||
|
||||
AudioOutData Data = MemoryHelper.Read<AudioOutData>(
|
||||
Context.Memory,
|
||||
Position);
|
||||
AudioOutData data = MemoryHelper.Read<AudioOutData>(
|
||||
context.Memory,
|
||||
position);
|
||||
|
||||
byte[] Buffer = Context.Memory.ReadBytes(
|
||||
Data.SampleBufferPtr,
|
||||
Data.SampleBufferSize);
|
||||
byte[] buffer = context.Memory.ReadBytes(
|
||||
data.SampleBufferPtr,
|
||||
data.SampleBufferSize);
|
||||
|
||||
AudioOut.AppendBuffer(Track, Tag, Buffer);
|
||||
_audioOut.AppendBuffer(_track, tag, buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetReleasedAudioOutBufferAuto(ServiceCtx Context)
|
||||
public long GetReleasedAudioOutBufferAuto(ServiceCtx context)
|
||||
{
|
||||
(long Position, long Size) = Context.Request.GetBufferType0x22();
|
||||
(long position, long size) = context.Request.GetBufferType0x22();
|
||||
|
||||
return GetReleasedAudioOutBufferImpl(Context, Position, Size);
|
||||
return GetReleasedAudioOutBufferImpl(context, position, size);
|
||||
}
|
||||
|
||||
public long GetReleasedAudioOutBufferImpl(ServiceCtx Context, long Position, long Size)
|
||||
public long GetReleasedAudioOutBufferImpl(ServiceCtx context, long position, long size)
|
||||
{
|
||||
uint Count = (uint)((ulong)Size >> 3);
|
||||
uint count = (uint)((ulong)size >> 3);
|
||||
|
||||
long[] ReleasedBuffers = AudioOut.GetReleasedBuffers(Track, (int)Count);
|
||||
long[] releasedBuffers = _audioOut.GetReleasedBuffers(_track, (int)count);
|
||||
|
||||
for (uint Index = 0; Index < Count; Index++)
|
||||
for (uint index = 0; index < count; index++)
|
||||
{
|
||||
long Tag = 0;
|
||||
long tag = 0;
|
||||
|
||||
if (Index < ReleasedBuffers.Length)
|
||||
if (index < releasedBuffers.Length)
|
||||
{
|
||||
Tag = ReleasedBuffers[Index];
|
||||
tag = releasedBuffers[index];
|
||||
}
|
||||
|
||||
Context.Memory.WriteInt64(Position + Index * 8, Tag);
|
||||
context.Memory.WriteInt64(position + index * 8, tag);
|
||||
}
|
||||
|
||||
Context.ResponseData.Write(ReleasedBuffers.Length);
|
||||
context.ResponseData.Write(releasedBuffers.Length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -153,11 +153,11 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioOut
|
|||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool Disposing)
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (Disposing)
|
||||
if (disposing)
|
||||
{
|
||||
AudioOut.CloseTrack(Track);
|
||||
_audioOut.CloseTrack(_track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,33 +22,33 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
//high latency).
|
||||
private const int MixBufferSamplesCount = 960;
|
||||
|
||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||
private Dictionary<int, ServiceProcessRequest> _commands;
|
||||
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
|
||||
|
||||
private KEvent UpdateEvent;
|
||||
private KEvent _updateEvent;
|
||||
|
||||
private MemoryManager Memory;
|
||||
private MemoryManager _memory;
|
||||
|
||||
private IAalOutput AudioOut;
|
||||
private IAalOutput _audioOut;
|
||||
|
||||
private AudioRendererParameter Params;
|
||||
private AudioRendererParameter _params;
|
||||
|
||||
private MemoryPoolContext[] MemoryPools;
|
||||
private MemoryPoolContext[] _memoryPools;
|
||||
|
||||
private VoiceContext[] Voices;
|
||||
private VoiceContext[] _voices;
|
||||
|
||||
private int Track;
|
||||
private int _track;
|
||||
|
||||
private PlayState PlayState;
|
||||
private PlayState _playState;
|
||||
|
||||
public IAudioRenderer(
|
||||
Horizon System,
|
||||
MemoryManager Memory,
|
||||
IAalOutput AudioOut,
|
||||
Horizon system,
|
||||
MemoryManager memory,
|
||||
IAalOutput audioOut,
|
||||
AudioRendererParameter Params)
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
_commands = new Dictionary<int, ServiceProcessRequest>
|
||||
{
|
||||
{ 0, GetSampleRate },
|
||||
{ 1, GetSampleCount },
|
||||
|
@ -60,75 +60,75 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
{ 7, QuerySystemEvent }
|
||||
};
|
||||
|
||||
UpdateEvent = new KEvent(System);
|
||||
_updateEvent = new KEvent(system);
|
||||
|
||||
this.Memory = Memory;
|
||||
this.AudioOut = AudioOut;
|
||||
this.Params = Params;
|
||||
_memory = memory;
|
||||
_audioOut = audioOut;
|
||||
_params = Params;
|
||||
|
||||
Track = AudioOut.OpenTrack(
|
||||
_track = audioOut.OpenTrack(
|
||||
AudioConsts.HostSampleRate,
|
||||
AudioConsts.HostChannelsCount,
|
||||
AudioCallback);
|
||||
|
||||
MemoryPools = CreateArray<MemoryPoolContext>(Params.EffectCount + Params.VoiceCount * 4);
|
||||
_memoryPools = CreateArray<MemoryPoolContext>(Params.EffectCount + Params.VoiceCount * 4);
|
||||
|
||||
Voices = CreateArray<VoiceContext>(Params.VoiceCount);
|
||||
_voices = CreateArray<VoiceContext>(Params.VoiceCount);
|
||||
|
||||
InitializeAudioOut();
|
||||
|
||||
PlayState = PlayState.Stopped;
|
||||
_playState = PlayState.Stopped;
|
||||
}
|
||||
|
||||
// GetSampleRate() -> u32
|
||||
public long GetSampleRate(ServiceCtx Context)
|
||||
public long GetSampleRate(ServiceCtx context)
|
||||
{
|
||||
Context.ResponseData.Write(Params.SampleRate);
|
||||
context.ResponseData.Write(_params.SampleRate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// GetSampleCount() -> u32
|
||||
public long GetSampleCount(ServiceCtx Context)
|
||||
public long GetSampleCount(ServiceCtx context)
|
||||
{
|
||||
Context.ResponseData.Write(Params.SampleCount);
|
||||
context.ResponseData.Write(_params.SampleCount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// GetMixBufferCount() -> u32
|
||||
public long GetMixBufferCount(ServiceCtx Context)
|
||||
public long GetMixBufferCount(ServiceCtx context)
|
||||
{
|
||||
Context.ResponseData.Write(Params.MixCount);
|
||||
context.ResponseData.Write(_params.MixCount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// GetState() -> u32
|
||||
private long GetState(ServiceCtx Context)
|
||||
private long GetState(ServiceCtx context)
|
||||
{
|
||||
Context.ResponseData.Write((int)PlayState);
|
||||
context.ResponseData.Write((int)_playState);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, $"Stubbed. Renderer State: {Enum.GetName(typeof(PlayState), PlayState)}");
|
||||
Logger.PrintStub(LogClass.ServiceAudio, $"Stubbed. Renderer State: {Enum.GetName(typeof(PlayState), _playState)}");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void AudioCallback()
|
||||
{
|
||||
UpdateEvent.ReadableEvent.Signal();
|
||||
_updateEvent.ReadableEvent.Signal();
|
||||
}
|
||||
|
||||
private static T[] CreateArray<T>(int Size) where T : new()
|
||||
private static T[] CreateArray<T>(int size) where T : new()
|
||||
{
|
||||
T[] Output = new T[Size];
|
||||
T[] output = new T[size];
|
||||
|
||||
for (int Index = 0; Index < Size; Index++)
|
||||
for (int index = 0; index < size; index++)
|
||||
{
|
||||
Output[Index] = new T();
|
||||
output[index] = new T();
|
||||
}
|
||||
|
||||
return Output;
|
||||
return output;
|
||||
}
|
||||
|
||||
private void InitializeAudioOut()
|
||||
|
@ -137,258 +137,258 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
AppendMixedBuffer(1);
|
||||
AppendMixedBuffer(2);
|
||||
|
||||
AudioOut.Start(Track);
|
||||
_audioOut.Start(_track);
|
||||
}
|
||||
|
||||
public long RequestUpdateAudioRenderer(ServiceCtx Context)
|
||||
public long RequestUpdateAudioRenderer(ServiceCtx context)
|
||||
{
|
||||
long OutputPosition = Context.Request.ReceiveBuff[0].Position;
|
||||
long OutputSize = Context.Request.ReceiveBuff[0].Size;
|
||||
long outputPosition = context.Request.ReceiveBuff[0].Position;
|
||||
long outputSize = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
MemoryHelper.FillWithZeros(Context.Memory, OutputPosition, (int)OutputSize);
|
||||
MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);
|
||||
|
||||
long InputPosition = Context.Request.SendBuff[0].Position;
|
||||
long inputPosition = context.Request.SendBuff[0].Position;
|
||||
|
||||
StructReader Reader = new StructReader(Context.Memory, InputPosition);
|
||||
StructWriter Writer = new StructWriter(Context.Memory, OutputPosition);
|
||||
StructReader reader = new StructReader(context.Memory, inputPosition);
|
||||
StructWriter writer = new StructWriter(context.Memory, outputPosition);
|
||||
|
||||
UpdateDataHeader InputHeader = Reader.Read<UpdateDataHeader>();
|
||||
UpdateDataHeader inputHeader = reader.Read<UpdateDataHeader>();
|
||||
|
||||
Reader.Read<BehaviorIn>(InputHeader.BehaviorSize);
|
||||
reader.Read<BehaviorIn>(inputHeader.BehaviorSize);
|
||||
|
||||
MemoryPoolIn[] MemoryPoolsIn = Reader.Read<MemoryPoolIn>(InputHeader.MemoryPoolSize);
|
||||
MemoryPoolIn[] memoryPoolsIn = reader.Read<MemoryPoolIn>(inputHeader.MemoryPoolSize);
|
||||
|
||||
for (int Index = 0; Index < MemoryPoolsIn.Length; Index++)
|
||||
for (int index = 0; index < memoryPoolsIn.Length; index++)
|
||||
{
|
||||
MemoryPoolIn MemoryPool = MemoryPoolsIn[Index];
|
||||
MemoryPoolIn memoryPool = memoryPoolsIn[index];
|
||||
|
||||
if (MemoryPool.State == MemoryPoolState.RequestAttach)
|
||||
if (memoryPool.State == MemoryPoolState.RequestAttach)
|
||||
{
|
||||
MemoryPools[Index].OutStatus.State = MemoryPoolState.Attached;
|
||||
_memoryPools[index].OutStatus.State = MemoryPoolState.Attached;
|
||||
}
|
||||
else if (MemoryPool.State == MemoryPoolState.RequestDetach)
|
||||
else if (memoryPool.State == MemoryPoolState.RequestDetach)
|
||||
{
|
||||
MemoryPools[Index].OutStatus.State = MemoryPoolState.Detached;
|
||||
_memoryPools[index].OutStatus.State = MemoryPoolState.Detached;
|
||||
}
|
||||
}
|
||||
|
||||
Reader.Read<VoiceChannelResourceIn>(InputHeader.VoiceResourceSize);
|
||||
reader.Read<VoiceChannelResourceIn>(inputHeader.VoiceResourceSize);
|
||||
|
||||
VoiceIn[] VoicesIn = Reader.Read<VoiceIn>(InputHeader.VoiceSize);
|
||||
VoiceIn[] voicesIn = reader.Read<VoiceIn>(inputHeader.VoiceSize);
|
||||
|
||||
for (int Index = 0; Index < VoicesIn.Length; Index++)
|
||||
for (int index = 0; index < voicesIn.Length; index++)
|
||||
{
|
||||
VoiceIn Voice = VoicesIn[Index];
|
||||
VoiceIn voice = voicesIn[index];
|
||||
|
||||
VoiceContext VoiceCtx = Voices[Index];
|
||||
VoiceContext voiceCtx = _voices[index];
|
||||
|
||||
VoiceCtx.SetAcquireState(Voice.Acquired != 0);
|
||||
voiceCtx.SetAcquireState(voice.Acquired != 0);
|
||||
|
||||
if (Voice.Acquired == 0)
|
||||
if (voice.Acquired == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Voice.FirstUpdate != 0)
|
||||
if (voice.FirstUpdate != 0)
|
||||
{
|
||||
VoiceCtx.AdpcmCtx = GetAdpcmDecoderContext(
|
||||
Voice.AdpcmCoeffsPosition,
|
||||
Voice.AdpcmCoeffsSize);
|
||||
voiceCtx.AdpcmCtx = GetAdpcmDecoderContext(
|
||||
voice.AdpcmCoeffsPosition,
|
||||
voice.AdpcmCoeffsSize);
|
||||
|
||||
VoiceCtx.SampleFormat = Voice.SampleFormat;
|
||||
VoiceCtx.SampleRate = Voice.SampleRate;
|
||||
VoiceCtx.ChannelsCount = Voice.ChannelsCount;
|
||||
voiceCtx.SampleFormat = voice.SampleFormat;
|
||||
voiceCtx.SampleRate = voice.SampleRate;
|
||||
voiceCtx.ChannelsCount = voice.ChannelsCount;
|
||||
|
||||
VoiceCtx.SetBufferIndex(Voice.BaseWaveBufferIndex);
|
||||
voiceCtx.SetBufferIndex(voice.BaseWaveBufferIndex);
|
||||
}
|
||||
|
||||
VoiceCtx.WaveBuffers[0] = Voice.WaveBuffer0;
|
||||
VoiceCtx.WaveBuffers[1] = Voice.WaveBuffer1;
|
||||
VoiceCtx.WaveBuffers[2] = Voice.WaveBuffer2;
|
||||
VoiceCtx.WaveBuffers[3] = Voice.WaveBuffer3;
|
||||
VoiceCtx.Volume = Voice.Volume;
|
||||
VoiceCtx.PlayState = Voice.PlayState;
|
||||
voiceCtx.WaveBuffers[0] = voice.WaveBuffer0;
|
||||
voiceCtx.WaveBuffers[1] = voice.WaveBuffer1;
|
||||
voiceCtx.WaveBuffers[2] = voice.WaveBuffer2;
|
||||
voiceCtx.WaveBuffers[3] = voice.WaveBuffer3;
|
||||
voiceCtx.Volume = voice.Volume;
|
||||
voiceCtx.PlayState = voice.PlayState;
|
||||
}
|
||||
|
||||
UpdateAudio();
|
||||
|
||||
UpdateDataHeader OutputHeader = new UpdateDataHeader();
|
||||
UpdateDataHeader outputHeader = new UpdateDataHeader();
|
||||
|
||||
int UpdateHeaderSize = Marshal.SizeOf<UpdateDataHeader>();
|
||||
int updateHeaderSize = Marshal.SizeOf<UpdateDataHeader>();
|
||||
|
||||
OutputHeader.Revision = IAudioRendererManager.RevMagic;
|
||||
OutputHeader.BehaviorSize = 0xb0;
|
||||
OutputHeader.MemoryPoolSize = (Params.EffectCount + Params.VoiceCount * 4) * 0x10;
|
||||
OutputHeader.VoiceSize = Params.VoiceCount * 0x10;
|
||||
OutputHeader.EffectSize = Params.EffectCount * 0x10;
|
||||
OutputHeader.SinkSize = Params.SinkCount * 0x20;
|
||||
OutputHeader.PerformanceManagerSize = 0x10;
|
||||
OutputHeader.TotalSize = UpdateHeaderSize +
|
||||
OutputHeader.BehaviorSize +
|
||||
OutputHeader.MemoryPoolSize +
|
||||
OutputHeader.VoiceSize +
|
||||
OutputHeader.EffectSize +
|
||||
OutputHeader.SinkSize +
|
||||
OutputHeader.PerformanceManagerSize;
|
||||
outputHeader.Revision = IAudioRendererManager.RevMagic;
|
||||
outputHeader.BehaviorSize = 0xb0;
|
||||
outputHeader.MemoryPoolSize = (_params.EffectCount + _params.VoiceCount * 4) * 0x10;
|
||||
outputHeader.VoiceSize = _params.VoiceCount * 0x10;
|
||||
outputHeader.EffectSize = _params.EffectCount * 0x10;
|
||||
outputHeader.SinkSize = _params.SinkCount * 0x20;
|
||||
outputHeader.PerformanceManagerSize = 0x10;
|
||||
outputHeader.TotalSize = updateHeaderSize +
|
||||
outputHeader.BehaviorSize +
|
||||
outputHeader.MemoryPoolSize +
|
||||
outputHeader.VoiceSize +
|
||||
outputHeader.EffectSize +
|
||||
outputHeader.SinkSize +
|
||||
outputHeader.PerformanceManagerSize;
|
||||
|
||||
Writer.Write(OutputHeader);
|
||||
writer.Write(outputHeader);
|
||||
|
||||
foreach (MemoryPoolContext MemoryPool in MemoryPools)
|
||||
foreach (MemoryPoolContext memoryPool in _memoryPools)
|
||||
{
|
||||
Writer.Write(MemoryPool.OutStatus);
|
||||
writer.Write(memoryPool.OutStatus);
|
||||
}
|
||||
|
||||
foreach (VoiceContext Voice in Voices)
|
||||
foreach (VoiceContext voice in _voices)
|
||||
{
|
||||
Writer.Write(Voice.OutStatus);
|
||||
writer.Write(voice.OutStatus);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long StartAudioRenderer(ServiceCtx Context)
|
||||
public long StartAudioRenderer(ServiceCtx context)
|
||||
{
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
PlayState = PlayState.Playing;
|
||||
_playState = PlayState.Playing;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long StopAudioRenderer(ServiceCtx Context)
|
||||
public long StopAudioRenderer(ServiceCtx context)
|
||||
{
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
PlayState = PlayState.Stopped;
|
||||
_playState = PlayState.Stopped;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long QuerySystemEvent(ServiceCtx Context)
|
||||
public long QuerySystemEvent(ServiceCtx context)
|
||||
{
|
||||
if (Context.Process.HandleTable.GenerateHandle(UpdateEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||
if (context.Process.HandleTable.GenerateHandle(_updateEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
||||
{
|
||||
throw new InvalidOperationException("Out of handles!");
|
||||
}
|
||||
|
||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private AdpcmDecoderContext GetAdpcmDecoderContext(long Position, long Size)
|
||||
private AdpcmDecoderContext GetAdpcmDecoderContext(long position, long size)
|
||||
{
|
||||
if (Size == 0)
|
||||
if (size == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
AdpcmDecoderContext Context = new AdpcmDecoderContext();
|
||||
AdpcmDecoderContext context = new AdpcmDecoderContext();
|
||||
|
||||
Context.Coefficients = new short[Size >> 1];
|
||||
context.Coefficients = new short[size >> 1];
|
||||
|
||||
for (int Offset = 0; Offset < Size; Offset += 2)
|
||||
for (int offset = 0; offset < size; offset += 2)
|
||||
{
|
||||
Context.Coefficients[Offset >> 1] = Memory.ReadInt16(Position + Offset);
|
||||
context.Coefficients[offset >> 1] = _memory.ReadInt16(position + offset);
|
||||
}
|
||||
|
||||
return Context;
|
||||
return context;
|
||||
}
|
||||
|
||||
private void UpdateAudio()
|
||||
{
|
||||
long[] Released = AudioOut.GetReleasedBuffers(Track, 2);
|
||||
long[] released = _audioOut.GetReleasedBuffers(_track, 2);
|
||||
|
||||
for (int Index = 0; Index < Released.Length; Index++)
|
||||
for (int index = 0; index < released.Length; index++)
|
||||
{
|
||||
AppendMixedBuffer(Released[Index]);
|
||||
AppendMixedBuffer(released[index]);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void AppendMixedBuffer(long Tag)
|
||||
private void AppendMixedBuffer(long tag)
|
||||
{
|
||||
int[] MixBuffer = new int[MixBufferSamplesCount * AudioConsts.HostChannelsCount];
|
||||
int[] mixBuffer = new int[MixBufferSamplesCount * AudioConsts.HostChannelsCount];
|
||||
|
||||
foreach (VoiceContext Voice in Voices)
|
||||
foreach (VoiceContext voice in _voices)
|
||||
{
|
||||
if (!Voice.Playing)
|
||||
if (!voice.Playing)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int OutOffset = 0;
|
||||
int PendingSamples = MixBufferSamplesCount;
|
||||
float Volume = Voice.Volume;
|
||||
int outOffset = 0;
|
||||
int pendingSamples = MixBufferSamplesCount;
|
||||
float volume = voice.Volume;
|
||||
|
||||
while (PendingSamples > 0)
|
||||
while (pendingSamples > 0)
|
||||
{
|
||||
int[] Samples = Voice.GetBufferData(Memory, PendingSamples, out int ReturnedSamples);
|
||||
int[] samples = voice.GetBufferData(_memory, pendingSamples, out int returnedSamples);
|
||||
|
||||
if (ReturnedSamples == 0)
|
||||
if (returnedSamples == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
PendingSamples -= ReturnedSamples;
|
||||
pendingSamples -= returnedSamples;
|
||||
|
||||
for (int Offset = 0; Offset < Samples.Length; Offset++)
|
||||
for (int offset = 0; offset < samples.Length; offset++)
|
||||
{
|
||||
MixBuffer[OutOffset++] += (int)(Samples[Offset] * Voice.Volume);
|
||||
mixBuffer[outOffset++] += (int)(samples[offset] * voice.Volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioOut.AppendBuffer(Track, Tag, GetFinalBuffer(MixBuffer));
|
||||
_audioOut.AppendBuffer(_track, tag, GetFinalBuffer(mixBuffer));
|
||||
}
|
||||
|
||||
private unsafe static short[] GetFinalBuffer(int[] Buffer)
|
||||
private static unsafe short[] GetFinalBuffer(int[] buffer)
|
||||
{
|
||||
short[] Output = new short[Buffer.Length];
|
||||
short[] output = new short[buffer.Length];
|
||||
|
||||
int Offset = 0;
|
||||
int offset = 0;
|
||||
|
||||
// Perform Saturation using SSE2 if supported
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
fixed (int* inptr = Buffer)
|
||||
fixed (short* outptr = Output)
|
||||
fixed (int* inptr = buffer)
|
||||
fixed (short* outptr = output)
|
||||
{
|
||||
for (; Offset + 32 <= Buffer.Length; Offset += 32)
|
||||
for (; offset + 32 <= buffer.Length; offset += 32)
|
||||
{
|
||||
// Unroll the loop a little to ensure the CPU pipeline
|
||||
// is always full.
|
||||
Vector128<int> block1A = Sse2.LoadVector128(inptr + Offset + 0);
|
||||
Vector128<int> block1B = Sse2.LoadVector128(inptr + Offset + 4);
|
||||
Vector128<int> block1A = Sse2.LoadVector128(inptr + offset + 0);
|
||||
Vector128<int> block1B = Sse2.LoadVector128(inptr + offset + 4);
|
||||
|
||||
Vector128<int> block2A = Sse2.LoadVector128(inptr + Offset + 8);
|
||||
Vector128<int> block2B = Sse2.LoadVector128(inptr + Offset + 12);
|
||||
Vector128<int> block2A = Sse2.LoadVector128(inptr + offset + 8);
|
||||
Vector128<int> block2B = Sse2.LoadVector128(inptr + offset + 12);
|
||||
|
||||
Vector128<int> block3A = Sse2.LoadVector128(inptr + Offset + 16);
|
||||
Vector128<int> block3B = Sse2.LoadVector128(inptr + Offset + 20);
|
||||
Vector128<int> block3A = Sse2.LoadVector128(inptr + offset + 16);
|
||||
Vector128<int> block3B = Sse2.LoadVector128(inptr + offset + 20);
|
||||
|
||||
Vector128<int> block4A = Sse2.LoadVector128(inptr + Offset + 24);
|
||||
Vector128<int> block4B = Sse2.LoadVector128(inptr + Offset + 28);
|
||||
Vector128<int> block4A = Sse2.LoadVector128(inptr + offset + 24);
|
||||
Vector128<int> block4B = Sse2.LoadVector128(inptr + offset + 28);
|
||||
|
||||
Vector128<short> output1 = Sse2.PackSignedSaturate(block1A, block1B);
|
||||
Vector128<short> output2 = Sse2.PackSignedSaturate(block2A, block2B);
|
||||
Vector128<short> output3 = Sse2.PackSignedSaturate(block3A, block3B);
|
||||
Vector128<short> output4 = Sse2.PackSignedSaturate(block4A, block4B);
|
||||
|
||||
Sse2.Store(outptr + Offset + 0, output1);
|
||||
Sse2.Store(outptr + Offset + 8, output2);
|
||||
Sse2.Store(outptr + Offset + 16, output3);
|
||||
Sse2.Store(outptr + Offset + 24, output4);
|
||||
Sse2.Store(outptr + offset + 0, output1);
|
||||
Sse2.Store(outptr + offset + 8, output2);
|
||||
Sse2.Store(outptr + offset + 16, output3);
|
||||
Sse2.Store(outptr + offset + 24, output4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process left overs
|
||||
for (; Offset < Buffer.Length; Offset++)
|
||||
for (; offset < buffer.Length; offset++)
|
||||
{
|
||||
Output[Offset] = DspUtils.Saturate(Buffer[Offset]);
|
||||
output[offset] = DspUtils.Saturate(buffer[offset]);
|
||||
}
|
||||
|
||||
return Output;
|
||||
return output;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -396,11 +396,11 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool Disposing)
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (Disposing)
|
||||
if (disposing)
|
||||
{
|
||||
AudioOut.CloseTrack(Track);
|
||||
_audioOut.CloseTrack(_track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
||||
{
|
||||
enum MemoryPoolState : int
|
||||
enum MemoryPoolState
|
||||
{
|
||||
Invalid = 0,
|
||||
Unknown = 1,
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
static class Resampler
|
||||
{
|
||||
#region "LookUp Tables"
|
||||
private static short[] CurveLut0 = new short[]
|
||||
private static short[] _curveLut0 = new short[]
|
||||
{
|
||||
6600, 19426, 6722, 3, 6479, 19424, 6845, 9, 6359, 19419, 6968, 15, 6239, 19412, 7093, 22,
|
||||
6121, 19403, 7219, 28, 6004, 19391, 7345, 34, 5888, 19377, 7472, 41, 5773, 19361, 7600, 48,
|
||||
|
@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424, 6479, 3, 6722, 19426, 6600
|
||||
};
|
||||
|
||||
private static short[] CurveLut1 = new short[]
|
||||
private static short[] _curveLut1 = new short[]
|
||||
{
|
||||
-68, 32639, 69, -5, -200, 32630, 212, -15, -328, 32613, 359, -26, -450, 32586, 512, -36,
|
||||
-568, 32551, 669, -47, -680, 32507, 832, -58, -788, 32454, 1000, -69, -891, 32393, 1174, -80,
|
||||
|
@ -77,7 +77,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
-36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630, -200, -5, 69, 32639, -68
|
||||
};
|
||||
|
||||
private static short[] CurveLut2 = new short[]
|
||||
private static short[] _curveLut2 = new short[]
|
||||
{
|
||||
3195, 26287, 3329, -32, 3064, 26281, 3467, -34, 2936, 26270, 3608, -38, 2811, 26253, 3751, -42,
|
||||
2688, 26230, 3897, -46, 2568, 26202, 4046, -50, 2451, 26169, 4199, -54, 2338, 26130, 4354, -58,
|
||||
|
@ -115,77 +115,77 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
#endregion
|
||||
|
||||
public static int[] Resample2Ch(
|
||||
int[] Buffer,
|
||||
int SrcSampleRate,
|
||||
int DstSampleRate,
|
||||
int SamplesCount,
|
||||
ref int FracPart)
|
||||
int[] buffer,
|
||||
int srcSampleRate,
|
||||
int dstSampleRate,
|
||||
int samplesCount,
|
||||
ref int fracPart)
|
||||
{
|
||||
if (Buffer == null)
|
||||
if (buffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Buffer));
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
if (SrcSampleRate <= 0)
|
||||
if (srcSampleRate <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(SrcSampleRate));
|
||||
throw new ArgumentOutOfRangeException(nameof(srcSampleRate));
|
||||
}
|
||||
|
||||
if (DstSampleRate <= 0)
|
||||
if (dstSampleRate <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(DstSampleRate));
|
||||
throw new ArgumentOutOfRangeException(nameof(dstSampleRate));
|
||||
}
|
||||
|
||||
double Ratio = (double)SrcSampleRate / DstSampleRate;
|
||||
double ratio = (double)srcSampleRate / dstSampleRate;
|
||||
|
||||
int NewSamplesCount = (int)(SamplesCount / Ratio);
|
||||
int newSamplesCount = (int)(samplesCount / ratio);
|
||||
|
||||
int Step = (int)(Ratio * 0x8000);
|
||||
int step = (int)(ratio * 0x8000);
|
||||
|
||||
int[] Output = new int[NewSamplesCount * 2];
|
||||
int[] output = new int[newSamplesCount * 2];
|
||||
|
||||
short[] Lut;
|
||||
short[] lut;
|
||||
|
||||
if (Step > 0xaaaa)
|
||||
if (step > 0xaaaa)
|
||||
{
|
||||
Lut = CurveLut0;
|
||||
lut = _curveLut0;
|
||||
}
|
||||
else if (Step <= 0x8000)
|
||||
else if (step <= 0x8000)
|
||||
{
|
||||
Lut = CurveLut1;
|
||||
lut = _curveLut1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Lut = CurveLut2;
|
||||
lut = _curveLut2;
|
||||
}
|
||||
|
||||
int InOffs = 0;
|
||||
int inOffs = 0;
|
||||
|
||||
for (int OutOffs = 0; OutOffs < Output.Length; OutOffs += 2)
|
||||
for (int outOffs = 0; outOffs < output.Length; outOffs += 2)
|
||||
{
|
||||
int LutIndex = (FracPart >> 8) * 4;
|
||||
int lutIndex = (fracPart >> 8) * 4;
|
||||
|
||||
int Sample0 = Buffer[(InOffs + 0) * 2 + 0] * Lut[LutIndex + 0] +
|
||||
Buffer[(InOffs + 1) * 2 + 0] * Lut[LutIndex + 1] +
|
||||
Buffer[(InOffs + 2) * 2 + 0] * Lut[LutIndex + 2] +
|
||||
Buffer[(InOffs + 3) * 2 + 0] * Lut[LutIndex + 3];
|
||||
int sample0 = buffer[(inOffs + 0) * 2 + 0] * lut[lutIndex + 0] +
|
||||
buffer[(inOffs + 1) * 2 + 0] * lut[lutIndex + 1] +
|
||||
buffer[(inOffs + 2) * 2 + 0] * lut[lutIndex + 2] +
|
||||
buffer[(inOffs + 3) * 2 + 0] * lut[lutIndex + 3];
|
||||
|
||||
int Sample1 = Buffer[(InOffs + 0) * 2 + 1] * Lut[LutIndex + 0] +
|
||||
Buffer[(InOffs + 1) * 2 + 1] * Lut[LutIndex + 1] +
|
||||
Buffer[(InOffs + 2) * 2 + 1] * Lut[LutIndex + 2] +
|
||||
Buffer[(InOffs + 3) * 2 + 1] * Lut[LutIndex + 3];
|
||||
int sample1 = buffer[(inOffs + 0) * 2 + 1] * lut[lutIndex + 0] +
|
||||
buffer[(inOffs + 1) * 2 + 1] * lut[lutIndex + 1] +
|
||||
buffer[(inOffs + 2) * 2 + 1] * lut[lutIndex + 2] +
|
||||
buffer[(inOffs + 3) * 2 + 1] * lut[lutIndex + 3];
|
||||
|
||||
int NewOffset = FracPart + Step;
|
||||
int newOffset = fracPart + step;
|
||||
|
||||
InOffs += NewOffset >> 15;
|
||||
inOffs += newOffset >> 15;
|
||||
|
||||
FracPart = NewOffset & 0x7fff;
|
||||
fracPart = newOffset & 0x7fff;
|
||||
|
||||
Output[OutOffs + 0] = Sample0 >> 15;
|
||||
Output[OutOffs + 1] = Sample1 >> 15;
|
||||
output[outOffs + 0] = sample0 >> 15;
|
||||
output[outOffs + 1] = sample1 >> 15;
|
||||
}
|
||||
|
||||
return Output;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,13 +6,13 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
{
|
||||
class VoiceContext
|
||||
{
|
||||
private bool Acquired;
|
||||
private bool BufferReload;
|
||||
private bool _acquired;
|
||||
private bool _bufferReload;
|
||||
|
||||
private int ResamplerFracPart;
|
||||
private int _resamplerFracPart;
|
||||
|
||||
private int BufferIndex;
|
||||
private int Offset;
|
||||
private int _bufferIndex;
|
||||
private int _offset;
|
||||
|
||||
public int SampleRate;
|
||||
public int ChannelsCount;
|
||||
|
@ -29,138 +29,138 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
|
||||
public VoiceOut OutStatus;
|
||||
|
||||
private int[] Samples;
|
||||
private int[] _samples;
|
||||
|
||||
public bool Playing => Acquired && PlayState == PlayState.Playing;
|
||||
public bool Playing => _acquired && PlayState == PlayState.Playing;
|
||||
|
||||
public VoiceContext()
|
||||
{
|
||||
WaveBuffers = new WaveBuffer[4];
|
||||
}
|
||||
|
||||
public void SetAcquireState(bool NewState)
|
||||
public void SetAcquireState(bool newState)
|
||||
{
|
||||
if (Acquired && !NewState)
|
||||
if (_acquired && !newState)
|
||||
{
|
||||
//Release.
|
||||
Reset();
|
||||
}
|
||||
|
||||
Acquired = NewState;
|
||||
_acquired = newState;
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
BufferReload = true;
|
||||
_bufferReload = true;
|
||||
|
||||
BufferIndex = 0;
|
||||
Offset = 0;
|
||||
_bufferIndex = 0;
|
||||
_offset = 0;
|
||||
|
||||
OutStatus.PlayedSamplesCount = 0;
|
||||
OutStatus.PlayedWaveBuffersCount = 0;
|
||||
OutStatus.VoiceDropsCount = 0;
|
||||
}
|
||||
|
||||
public int[] GetBufferData(MemoryManager Memory, int MaxSamples, out int SamplesCount)
|
||||
public int[] GetBufferData(MemoryManager memory, int maxSamples, out int samplesCount)
|
||||
{
|
||||
if (!Playing)
|
||||
{
|
||||
SamplesCount = 0;
|
||||
samplesCount = 0;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (BufferReload)
|
||||
if (_bufferReload)
|
||||
{
|
||||
BufferReload = false;
|
||||
_bufferReload = false;
|
||||
|
||||
UpdateBuffer(Memory);
|
||||
UpdateBuffer(memory);
|
||||
}
|
||||
|
||||
WaveBuffer Wb = WaveBuffers[BufferIndex];
|
||||
WaveBuffer wb = WaveBuffers[_bufferIndex];
|
||||
|
||||
int MaxSize = Samples.Length - Offset;
|
||||
int maxSize = _samples.Length - _offset;
|
||||
|
||||
int Size = MaxSamples * AudioConsts.HostChannelsCount;
|
||||
int size = maxSamples * AudioConsts.HostChannelsCount;
|
||||
|
||||
if (Size > MaxSize)
|
||||
if (size > maxSize)
|
||||
{
|
||||
Size = MaxSize;
|
||||
size = maxSize;
|
||||
}
|
||||
|
||||
int[] Output = new int[Size];
|
||||
int[] output = new int[size];
|
||||
|
||||
Array.Copy(Samples, Offset, Output, 0, Size);
|
||||
Array.Copy(_samples, _offset, output, 0, size);
|
||||
|
||||
SamplesCount = Size / AudioConsts.HostChannelsCount;
|
||||
samplesCount = size / AudioConsts.HostChannelsCount;
|
||||
|
||||
OutStatus.PlayedSamplesCount += SamplesCount;
|
||||
OutStatus.PlayedSamplesCount += samplesCount;
|
||||
|
||||
Offset += Size;
|
||||
_offset += size;
|
||||
|
||||
if (Offset == Samples.Length)
|
||||
if (_offset == _samples.Length)
|
||||
{
|
||||
Offset = 0;
|
||||
_offset = 0;
|
||||
|
||||
if (Wb.Looping == 0)
|
||||
if (wb.Looping == 0)
|
||||
{
|
||||
SetBufferIndex((BufferIndex + 1) & 3);
|
||||
SetBufferIndex((_bufferIndex + 1) & 3);
|
||||
}
|
||||
|
||||
OutStatus.PlayedWaveBuffersCount++;
|
||||
|
||||
if (Wb.LastBuffer != 0)
|
||||
if (wb.LastBuffer != 0)
|
||||
{
|
||||
PlayState = PlayState.Paused;
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
return output;
|
||||
}
|
||||
|
||||
private void UpdateBuffer(MemoryManager Memory)
|
||||
private void UpdateBuffer(MemoryManager memory)
|
||||
{
|
||||
//TODO: Implement conversion for formats other
|
||||
//than interleaved stereo (2 channels).
|
||||
//As of now, it assumes that HostChannelsCount == 2.
|
||||
WaveBuffer Wb = WaveBuffers[BufferIndex];
|
||||
WaveBuffer wb = WaveBuffers[_bufferIndex];
|
||||
|
||||
if (Wb.Position == 0)
|
||||
if (wb.Position == 0)
|
||||
{
|
||||
Samples = new int[0];
|
||||
_samples = new int[0];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (SampleFormat == SampleFormat.PcmInt16)
|
||||
{
|
||||
int SamplesCount = (int)(Wb.Size / (sizeof(short) * ChannelsCount));
|
||||
int samplesCount = (int)(wb.Size / (sizeof(short) * ChannelsCount));
|
||||
|
||||
Samples = new int[SamplesCount * AudioConsts.HostChannelsCount];
|
||||
_samples = new int[samplesCount * AudioConsts.HostChannelsCount];
|
||||
|
||||
if (ChannelsCount == 1)
|
||||
{
|
||||
for (int Index = 0; Index < SamplesCount; Index++)
|
||||
for (int index = 0; index < samplesCount; index++)
|
||||
{
|
||||
short Sample = Memory.ReadInt16(Wb.Position + Index * 2);
|
||||
short sample = memory.ReadInt16(wb.Position + index * 2);
|
||||
|
||||
Samples[Index * 2 + 0] = Sample;
|
||||
Samples[Index * 2 + 1] = Sample;
|
||||
_samples[index * 2 + 0] = sample;
|
||||
_samples[index * 2 + 1] = sample;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int Index = 0; Index < SamplesCount * 2; Index++)
|
||||
for (int index = 0; index < samplesCount * 2; index++)
|
||||
{
|
||||
Samples[Index] = Memory.ReadInt16(Wb.Position + Index * 2);
|
||||
_samples[index] = memory.ReadInt16(wb.Position + index * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (SampleFormat == SampleFormat.Adpcm)
|
||||
{
|
||||
byte[] Buffer = Memory.ReadBytes(Wb.Position, Wb.Size);
|
||||
byte[] buffer = memory.ReadBytes(wb.Position, wb.Size);
|
||||
|
||||
Samples = AdpcmDecoder.Decode(Buffer, AdpcmCtx);
|
||||
_samples = AdpcmDecoder.Decode(buffer, AdpcmCtx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -172,24 +172,24 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
|||
//TODO: We should keep the frames being discarded (see the 4 below)
|
||||
//on a buffer and include it on the next samples buffer, to allow
|
||||
//the resampler to do seamless interpolation between wave buffers.
|
||||
int SamplesCount = Samples.Length / AudioConsts.HostChannelsCount;
|
||||
int samplesCount = _samples.Length / AudioConsts.HostChannelsCount;
|
||||
|
||||
SamplesCount = Math.Max(SamplesCount - 4, 0);
|
||||
samplesCount = Math.Max(samplesCount - 4, 0);
|
||||
|
||||
Samples = Resampler.Resample2Ch(
|
||||
Samples,
|
||||
_samples = Resampler.Resample2Ch(
|
||||
_samples,
|
||||
SampleRate,
|
||||
AudioConsts.HostSampleRate,
|
||||
SamplesCount,
|
||||
ref ResamplerFracPart);
|
||||
samplesCount,
|
||||
ref _resamplerFracPart);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBufferIndex(int Index)
|
||||
public void SetBufferIndex(int index)
|
||||
{
|
||||
BufferIndex = Index & 3;
|
||||
_bufferIndex = index & 3;
|
||||
|
||||
BufferReload = true;
|
||||
_bufferReload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,15 +10,15 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
{
|
||||
class IAudioDevice : IpcService
|
||||
{
|
||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||
private Dictionary<int, ServiceProcessRequest> _commands;
|
||||
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
|
||||
|
||||
private KEvent SystemEvent;
|
||||
private KEvent _systemEvent;
|
||||
|
||||
public IAudioDevice(Horizon System)
|
||||
public IAudioDevice(Horizon system)
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
_commands = new Dictionary<int, ServiceProcessRequest>
|
||||
{
|
||||
{ 0, ListAudioDeviceName },
|
||||
{ 1, SetAudioDeviceOutputVolume },
|
||||
|
@ -33,197 +33,197 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
{ 12, QueryAudioDeviceOutputEvent }
|
||||
};
|
||||
|
||||
SystemEvent = new KEvent(System);
|
||||
_systemEvent = new KEvent(system);
|
||||
|
||||
//TODO: We shouldn't be signaling this here.
|
||||
SystemEvent.ReadableEvent.Signal();
|
||||
_systemEvent.ReadableEvent.Signal();
|
||||
}
|
||||
|
||||
public long ListAudioDeviceName(ServiceCtx Context)
|
||||
public long ListAudioDeviceName(ServiceCtx context)
|
||||
{
|
||||
string[] DeviceNames = SystemStateMgr.AudioOutputs;
|
||||
string[] deviceNames = SystemStateMgr.AudioOutputs;
|
||||
|
||||
Context.ResponseData.Write(DeviceNames.Length);
|
||||
context.ResponseData.Write(deviceNames.Length);
|
||||
|
||||
long Position = Context.Request.ReceiveBuff[0].Position;
|
||||
long Size = Context.Request.ReceiveBuff[0].Size;
|
||||
long position = context.Request.ReceiveBuff[0].Position;
|
||||
long size = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
long BasePosition = Position;
|
||||
long basePosition = position;
|
||||
|
||||
foreach (string Name in DeviceNames)
|
||||
foreach (string name in deviceNames)
|
||||
{
|
||||
byte[] Buffer = Encoding.ASCII.GetBytes(Name + "\0");
|
||||
byte[] buffer = Encoding.ASCII.GetBytes(name + "\0");
|
||||
|
||||
if ((Position - BasePosition) + Buffer.Length > Size)
|
||||
if ((position - basePosition) + buffer.Length > size)
|
||||
{
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {size} too small!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Context.Memory.WriteBytes(Position, Buffer);
|
||||
context.Memory.WriteBytes(position, buffer);
|
||||
|
||||
Position += Buffer.Length;
|
||||
position += buffer.Length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long SetAudioDeviceOutputVolume(ServiceCtx Context)
|
||||
public long SetAudioDeviceOutputVolume(ServiceCtx context)
|
||||
{
|
||||
float Volume = Context.RequestData.ReadSingle();
|
||||
float volume = context.RequestData.ReadSingle();
|
||||
|
||||
long Position = Context.Request.SendBuff[0].Position;
|
||||
long Size = Context.Request.SendBuff[0].Size;
|
||||
long position = context.Request.SendBuff[0].Position;
|
||||
long size = context.Request.SendBuff[0].Size;
|
||||
|
||||
byte[] DeviceNameBuffer = Context.Memory.ReadBytes(Position, Size);
|
||||
byte[] deviceNameBuffer = context.Memory.ReadBytes(position, size);
|
||||
|
||||
string DeviceName = Encoding.ASCII.GetString(DeviceNameBuffer);
|
||||
string deviceName = Encoding.ASCII.GetString(deviceNameBuffer);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetActiveAudioDeviceName(ServiceCtx Context)
|
||||
public long GetActiveAudioDeviceName(ServiceCtx context)
|
||||
{
|
||||
string Name = Context.Device.System.State.ActiveAudioOutput;
|
||||
string name = context.Device.System.State.ActiveAudioOutput;
|
||||
|
||||
long Position = Context.Request.ReceiveBuff[0].Position;
|
||||
long Size = Context.Request.ReceiveBuff[0].Size;
|
||||
long position = context.Request.ReceiveBuff[0].Position;
|
||||
long size = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(Name + "\0");
|
||||
byte[] deviceNameBuffer = Encoding.ASCII.GetBytes(name + "\0");
|
||||
|
||||
if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
|
||||
if ((ulong)deviceNameBuffer.Length <= (ulong)size)
|
||||
{
|
||||
Context.Memory.WriteBytes(Position, DeviceNameBuffer);
|
||||
context.Memory.WriteBytes(position, deviceNameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {size} too small!");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long QueryAudioDeviceSystemEvent(ServiceCtx Context)
|
||||
public long QueryAudioDeviceSystemEvent(ServiceCtx context)
|
||||
{
|
||||
if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||
if (context.Process.HandleTable.GenerateHandle(_systemEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
||||
{
|
||||
throw new InvalidOperationException("Out of handles!");
|
||||
}
|
||||
|
||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetActiveChannelCount(ServiceCtx Context)
|
||||
public long GetActiveChannelCount(ServiceCtx context)
|
||||
{
|
||||
Context.ResponseData.Write(2);
|
||||
context.ResponseData.Write(2);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long ListAudioDeviceNameAuto(ServiceCtx Context)
|
||||
public long ListAudioDeviceNameAuto(ServiceCtx context)
|
||||
{
|
||||
string[] DeviceNames = SystemStateMgr.AudioOutputs;
|
||||
string[] deviceNames = SystemStateMgr.AudioOutputs;
|
||||
|
||||
Context.ResponseData.Write(DeviceNames.Length);
|
||||
context.ResponseData.Write(deviceNames.Length);
|
||||
|
||||
(long Position, long Size) = Context.Request.GetBufferType0x22();
|
||||
(long position, long size) = context.Request.GetBufferType0x22();
|
||||
|
||||
long BasePosition = Position;
|
||||
long basePosition = position;
|
||||
|
||||
foreach (string Name in DeviceNames)
|
||||
foreach (string name in deviceNames)
|
||||
{
|
||||
byte[] Buffer = Encoding.UTF8.GetBytes(Name + '\0');
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(name + '\0');
|
||||
|
||||
if ((Position - BasePosition) + Buffer.Length > Size)
|
||||
if ((position - basePosition) + buffer.Length > size)
|
||||
{
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {size} too small!");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Context.Memory.WriteBytes(Position, Buffer);
|
||||
context.Memory.WriteBytes(position, buffer);
|
||||
|
||||
Position += Buffer.Length;
|
||||
position += buffer.Length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long SetAudioDeviceOutputVolumeAuto(ServiceCtx Context)
|
||||
public long SetAudioDeviceOutputVolumeAuto(ServiceCtx context)
|
||||
{
|
||||
float Volume = Context.RequestData.ReadSingle();
|
||||
float volume = context.RequestData.ReadSingle();
|
||||
|
||||
(long Position, long Size) = Context.Request.GetBufferType0x21();
|
||||
(long position, long size) = context.Request.GetBufferType0x21();
|
||||
|
||||
byte[] DeviceNameBuffer = Context.Memory.ReadBytes(Position, Size);
|
||||
byte[] deviceNameBuffer = context.Memory.ReadBytes(position, size);
|
||||
|
||||
string DeviceName = Encoding.UTF8.GetString(DeviceNameBuffer);
|
||||
string deviceName = Encoding.UTF8.GetString(deviceNameBuffer);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetAudioDeviceOutputVolumeAuto(ServiceCtx Context)
|
||||
public long GetAudioDeviceOutputVolumeAuto(ServiceCtx context)
|
||||
{
|
||||
Context.ResponseData.Write(1f);
|
||||
context.ResponseData.Write(1f);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetActiveAudioDeviceNameAuto(ServiceCtx Context)
|
||||
public long GetActiveAudioDeviceNameAuto(ServiceCtx context)
|
||||
{
|
||||
string Name = Context.Device.System.State.ActiveAudioOutput;
|
||||
string name = context.Device.System.State.ActiveAudioOutput;
|
||||
|
||||
(long Position, long Size) = Context.Request.GetBufferType0x22();
|
||||
(long position, long size) = context.Request.GetBufferType0x22();
|
||||
|
||||
byte[] DeviceNameBuffer = Encoding.UTF8.GetBytes(Name + '\0');
|
||||
byte[] deviceNameBuffer = Encoding.UTF8.GetBytes(name + '\0');
|
||||
|
||||
if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
|
||||
if ((ulong)deviceNameBuffer.Length <= (ulong)size)
|
||||
{
|
||||
Context.Memory.WriteBytes(Position, DeviceNameBuffer);
|
||||
context.Memory.WriteBytes(position, deviceNameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {size} too small!");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long QueryAudioDeviceInputEvent(ServiceCtx Context)
|
||||
public long QueryAudioDeviceInputEvent(ServiceCtx context)
|
||||
{
|
||||
if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||
if (context.Process.HandleTable.GenerateHandle(_systemEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
||||
{
|
||||
throw new InvalidOperationException("Out of handles!");
|
||||
}
|
||||
|
||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long QueryAudioDeviceOutputEvent(ServiceCtx Context)
|
||||
public long QueryAudioDeviceOutputEvent(ServiceCtx context)
|
||||
{
|
||||
if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||
if (context.Process.HandleTable.GenerateHandle(_systemEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
||||
{
|
||||
throw new InvalidOperationException("Out of handles!");
|
||||
}
|
||||
|
||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, "Stubbed.");
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
|
||||
private const int DefaultChannelsCount = 2;
|
||||
|
||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||
private Dictionary<int, ServiceProcessRequest> _commands;
|
||||
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
|
||||
|
||||
public IAudioOutManager()
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
_commands = new Dictionary<int, ServiceProcessRequest>
|
||||
{
|
||||
{ 0, ListAudioOuts },
|
||||
{ 1, OpenAudioOut },
|
||||
|
@ -34,135 +34,135 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
};
|
||||
}
|
||||
|
||||
public long ListAudioOuts(ServiceCtx Context)
|
||||
public long ListAudioOuts(ServiceCtx context)
|
||||
{
|
||||
return ListAudioOutsImpl(
|
||||
Context,
|
||||
Context.Request.ReceiveBuff[0].Position,
|
||||
Context.Request.ReceiveBuff[0].Size);
|
||||
context,
|
||||
context.Request.ReceiveBuff[0].Position,
|
||||
context.Request.ReceiveBuff[0].Size);
|
||||
}
|
||||
|
||||
public long OpenAudioOut(ServiceCtx Context)
|
||||
public long OpenAudioOut(ServiceCtx context)
|
||||
{
|
||||
return OpenAudioOutImpl(
|
||||
Context,
|
||||
Context.Request.SendBuff[0].Position,
|
||||
Context.Request.SendBuff[0].Size,
|
||||
Context.Request.ReceiveBuff[0].Position,
|
||||
Context.Request.ReceiveBuff[0].Size);
|
||||
context,
|
||||
context.Request.SendBuff[0].Position,
|
||||
context.Request.SendBuff[0].Size,
|
||||
context.Request.ReceiveBuff[0].Position,
|
||||
context.Request.ReceiveBuff[0].Size);
|
||||
}
|
||||
|
||||
public long ListAudioOutsAuto(ServiceCtx Context)
|
||||
public long ListAudioOutsAuto(ServiceCtx context)
|
||||
{
|
||||
(long RecvPosition, long RecvSize) = Context.Request.GetBufferType0x22();
|
||||
(long recvPosition, long recvSize) = context.Request.GetBufferType0x22();
|
||||
|
||||
return ListAudioOutsImpl(Context, RecvPosition, RecvSize);
|
||||
return ListAudioOutsImpl(context, recvPosition, recvSize);
|
||||
}
|
||||
|
||||
public long OpenAudioOutAuto(ServiceCtx Context)
|
||||
public long OpenAudioOutAuto(ServiceCtx context)
|
||||
{
|
||||
(long SendPosition, long SendSize) = Context.Request.GetBufferType0x21();
|
||||
(long RecvPosition, long RecvSize) = Context.Request.GetBufferType0x22();
|
||||
(long sendPosition, long sendSize) = context.Request.GetBufferType0x21();
|
||||
(long recvPosition, long recvSize) = context.Request.GetBufferType0x22();
|
||||
|
||||
return OpenAudioOutImpl(
|
||||
Context,
|
||||
SendPosition,
|
||||
SendSize,
|
||||
RecvPosition,
|
||||
RecvSize);
|
||||
context,
|
||||
sendPosition,
|
||||
sendSize,
|
||||
recvPosition,
|
||||
recvSize);
|
||||
}
|
||||
|
||||
private long ListAudioOutsImpl(ServiceCtx Context, long Position, long Size)
|
||||
private long ListAudioOutsImpl(ServiceCtx context, long position, long size)
|
||||
{
|
||||
int NameCount = 0;
|
||||
int nameCount = 0;
|
||||
|
||||
byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DefaultAudioOutput + "\0");
|
||||
byte[] deviceNameBuffer = Encoding.ASCII.GetBytes(DefaultAudioOutput + "\0");
|
||||
|
||||
if ((ulong)DeviceNameBuffer.Length <= (ulong)Size)
|
||||
if ((ulong)deviceNameBuffer.Length <= (ulong)size)
|
||||
{
|
||||
Context.Memory.WriteBytes(Position, DeviceNameBuffer);
|
||||
context.Memory.WriteBytes(position, deviceNameBuffer);
|
||||
|
||||
NameCount++;
|
||||
nameCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {Size} too small!");
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {size} too small!");
|
||||
}
|
||||
|
||||
Context.ResponseData.Write(NameCount);
|
||||
context.ResponseData.Write(nameCount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private long OpenAudioOutImpl(ServiceCtx Context, long SendPosition, long SendSize, long ReceivePosition, long ReceiveSize)
|
||||
private long OpenAudioOutImpl(ServiceCtx context, long sendPosition, long sendSize, long receivePosition, long receiveSize)
|
||||
{
|
||||
string DeviceName = MemoryHelper.ReadAsciiString(
|
||||
Context.Memory,
|
||||
SendPosition,
|
||||
SendSize);
|
||||
string deviceName = MemoryHelper.ReadAsciiString(
|
||||
context.Memory,
|
||||
sendPosition,
|
||||
sendSize);
|
||||
|
||||
if (DeviceName == string.Empty)
|
||||
if (deviceName == string.Empty)
|
||||
{
|
||||
DeviceName = DefaultAudioOutput;
|
||||
deviceName = DefaultAudioOutput;
|
||||
}
|
||||
|
||||
if (DeviceName != DefaultAudioOutput)
|
||||
if (deviceName != DefaultAudioOutput)
|
||||
{
|
||||
Logger.PrintWarning(LogClass.Audio, "Invalid device name!");
|
||||
|
||||
return MakeError(ErrorModule.Audio, AudErr.DeviceNotFound);
|
||||
}
|
||||
|
||||
byte[] DeviceNameBuffer = Encoding.ASCII.GetBytes(DeviceName + "\0");
|
||||
byte[] deviceNameBuffer = Encoding.ASCII.GetBytes(deviceName + "\0");
|
||||
|
||||
if ((ulong)DeviceNameBuffer.Length <= (ulong)ReceiveSize)
|
||||
if ((ulong)deviceNameBuffer.Length <= (ulong)receiveSize)
|
||||
{
|
||||
Context.Memory.WriteBytes(ReceivePosition, DeviceNameBuffer);
|
||||
context.Memory.WriteBytes(receivePosition, deviceNameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {ReceiveSize} too small!");
|
||||
Logger.PrintError(LogClass.ServiceAudio, $"Output buffer size {receiveSize} too small!");
|
||||
}
|
||||
|
||||
int SampleRate = Context.RequestData.ReadInt32();
|
||||
int Channels = Context.RequestData.ReadInt32();
|
||||
int sampleRate = context.RequestData.ReadInt32();
|
||||
int channels = context.RequestData.ReadInt32();
|
||||
|
||||
if (SampleRate == 0)
|
||||
if (sampleRate == 0)
|
||||
{
|
||||
SampleRate = DefaultSampleRate;
|
||||
sampleRate = DefaultSampleRate;
|
||||
}
|
||||
|
||||
if (SampleRate != DefaultSampleRate)
|
||||
if (sampleRate != DefaultSampleRate)
|
||||
{
|
||||
Logger.PrintWarning(LogClass.Audio, "Invalid sample rate!");
|
||||
|
||||
return MakeError(ErrorModule.Audio, AudErr.UnsupportedSampleRate);
|
||||
}
|
||||
|
||||
Channels = (ushort)Channels;
|
||||
channels = (ushort)channels;
|
||||
|
||||
if (Channels == 0)
|
||||
if (channels == 0)
|
||||
{
|
||||
Channels = DefaultChannelsCount;
|
||||
channels = DefaultChannelsCount;
|
||||
}
|
||||
|
||||
KEvent ReleaseEvent = new KEvent(Context.Device.System);
|
||||
KEvent releaseEvent = new KEvent(context.Device.System);
|
||||
|
||||
ReleaseCallback Callback = () =>
|
||||
ReleaseCallback callback = () =>
|
||||
{
|
||||
ReleaseEvent.ReadableEvent.Signal();
|
||||
releaseEvent.ReadableEvent.Signal();
|
||||
};
|
||||
|
||||
IAalOutput AudioOut = Context.Device.AudioOut;
|
||||
IAalOutput audioOut = context.Device.AudioOut;
|
||||
|
||||
int Track = AudioOut.OpenTrack(SampleRate, Channels, Callback);
|
||||
int track = audioOut.OpenTrack(sampleRate, channels, callback);
|
||||
|
||||
MakeObject(Context, new IAudioOut(AudioOut, ReleaseEvent, Track));
|
||||
MakeObject(context, new IAudioOut(audioOut, releaseEvent, track));
|
||||
|
||||
Context.ResponseData.Write(SampleRate);
|
||||
Context.ResponseData.Write(Channels);
|
||||
Context.ResponseData.Write((int)SampleFormat.PcmInt16);
|
||||
Context.ResponseData.Write((int)PlaybackState.Stopped);
|
||||
context.ResponseData.Write(sampleRate);
|
||||
context.ResponseData.Write(channels);
|
||||
context.ResponseData.Write((int)SampleFormat.PcmInt16);
|
||||
context.ResponseData.Write((int)PlaybackState.Stopped);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,13 +20,13 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
|
||||
public const int RevMagic = Rev0Magic + (Rev << 24);
|
||||
|
||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||
private Dictionary<int, ServiceProcessRequest> _commands;
|
||||
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
|
||||
|
||||
public IAudioRendererManager()
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
_commands = new Dictionary<int, ServiceProcessRequest>
|
||||
{
|
||||
{ 0, OpenAudioRenderer },
|
||||
{ 1, GetAudioRendererWorkBufferSize },
|
||||
|
@ -35,81 +35,81 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
};
|
||||
}
|
||||
|
||||
public long OpenAudioRenderer(ServiceCtx Context)
|
||||
public long OpenAudioRenderer(ServiceCtx context)
|
||||
{
|
||||
IAalOutput AudioOut = Context.Device.AudioOut;
|
||||
IAalOutput audioOut = context.Device.AudioOut;
|
||||
|
||||
AudioRendererParameter Params = GetAudioRendererParameter(Context);
|
||||
AudioRendererParameter Params = GetAudioRendererParameter(context);
|
||||
|
||||
MakeObject(Context, new IAudioRenderer(
|
||||
Context.Device.System,
|
||||
Context.Memory,
|
||||
AudioOut,
|
||||
MakeObject(context, new IAudioRenderer(
|
||||
context.Device.System,
|
||||
context.Memory,
|
||||
audioOut,
|
||||
Params));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetAudioRendererWorkBufferSize(ServiceCtx Context)
|
||||
public long GetAudioRendererWorkBufferSize(ServiceCtx context)
|
||||
{
|
||||
AudioRendererParameter Params = GetAudioRendererParameter(Context);
|
||||
AudioRendererParameter Params = GetAudioRendererParameter(context);
|
||||
|
||||
int Revision = (Params.Revision - Rev0Magic) >> 24;
|
||||
int revision = (Params.Revision - Rev0Magic) >> 24;
|
||||
|
||||
if (Revision <= Rev)
|
||||
if (revision <= Rev)
|
||||
{
|
||||
bool IsSplitterSupported = Revision >= 3;
|
||||
bool isSplitterSupported = revision >= 3;
|
||||
|
||||
long Size;
|
||||
long size;
|
||||
|
||||
Size = IntUtils.AlignUp(Params.Unknown8 * 4, 64);
|
||||
Size += Params.MixCount * 0x400;
|
||||
Size += (Params.MixCount + 1) * 0x940;
|
||||
Size += Params.VoiceCount * 0x3F0;
|
||||
Size += IntUtils.AlignUp((Params.MixCount + 1) * 8, 16);
|
||||
Size += IntUtils.AlignUp(Params.VoiceCount * 8, 16);
|
||||
Size += IntUtils.AlignUp(
|
||||
size = IntUtils.AlignUp(Params.Unknown8 * 4, 64);
|
||||
size += Params.MixCount * 0x400;
|
||||
size += (Params.MixCount + 1) * 0x940;
|
||||
size += Params.VoiceCount * 0x3F0;
|
||||
size += IntUtils.AlignUp((Params.MixCount + 1) * 8, 16);
|
||||
size += IntUtils.AlignUp(Params.VoiceCount * 8, 16);
|
||||
size += IntUtils.AlignUp(
|
||||
((Params.SinkCount + Params.MixCount) * 0x3C0 + Params.SampleCount * 4) *
|
||||
(Params.Unknown8 + 6), 64);
|
||||
Size += (Params.SinkCount + Params.MixCount) * 0x2C0;
|
||||
Size += (Params.EffectCount + Params.VoiceCount * 4) * 0x30 + 0x50;
|
||||
size += (Params.SinkCount + Params.MixCount) * 0x2C0;
|
||||
size += (Params.EffectCount + Params.VoiceCount * 4) * 0x30 + 0x50;
|
||||
|
||||
if (IsSplitterSupported)
|
||||
if (isSplitterSupported)
|
||||
{
|
||||
Size += IntUtils.AlignUp((
|
||||
size += IntUtils.AlignUp((
|
||||
NodeStatesGetWorkBufferSize(Params.MixCount + 1) +
|
||||
EdgeMatrixGetWorkBufferSize(Params.MixCount + 1)), 16);
|
||||
|
||||
Size += Params.SplitterDestinationDataCount * 0xE0;
|
||||
Size += Params.SplitterCount * 0x20;
|
||||
Size += IntUtils.AlignUp(Params.SplitterDestinationDataCount * 4, 16);
|
||||
size += Params.SplitterDestinationDataCount * 0xE0;
|
||||
size += Params.SplitterCount * 0x20;
|
||||
size += IntUtils.AlignUp(Params.SplitterDestinationDataCount * 4, 16);
|
||||
}
|
||||
|
||||
Size = Params.EffectCount * 0x4C0 +
|
||||
size = Params.EffectCount * 0x4C0 +
|
||||
Params.SinkCount * 0x170 +
|
||||
Params.VoiceCount * 0x100 +
|
||||
IntUtils.AlignUp(Size, 64) + 0x40;
|
||||
IntUtils.AlignUp(size, 64) + 0x40;
|
||||
|
||||
if (Params.PerformanceManagerCount >= 1)
|
||||
{
|
||||
Size += (((Params.EffectCount +
|
||||
size += (((Params.EffectCount +
|
||||
Params.SinkCount +
|
||||
Params.VoiceCount +
|
||||
Params.MixCount + 1) * 16 + 0x658) *
|
||||
(Params.PerformanceManagerCount + 1) + 0x13F) & ~0x3FL;
|
||||
}
|
||||
|
||||
Size = (Size + 0x1907D) & ~0xFFFL;
|
||||
size = (size + 0x1907D) & ~0xFFFL;
|
||||
|
||||
Context.ResponseData.Write(Size);
|
||||
context.ResponseData.Write(size);
|
||||
|
||||
Logger.PrintDebug(LogClass.ServiceAudio, $"WorkBufferSize is 0x{Size:x16}.");
|
||||
Logger.PrintDebug(LogClass.ServiceAudio, $"WorkBufferSize is 0x{size:x16}.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.ResponseData.Write(0L);
|
||||
context.ResponseData.Write(0L);
|
||||
|
||||
Logger.PrintWarning(LogClass.ServiceAudio, $"Library Revision 0x{Params.Revision:x8} is not supported!");
|
||||
|
||||
|
@ -117,71 +117,71 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
}
|
||||
}
|
||||
|
||||
private AudioRendererParameter GetAudioRendererParameter(ServiceCtx Context)
|
||||
private AudioRendererParameter GetAudioRendererParameter(ServiceCtx context)
|
||||
{
|
||||
AudioRendererParameter Params = new AudioRendererParameter();
|
||||
|
||||
Params.SampleRate = Context.RequestData.ReadInt32();
|
||||
Params.SampleCount = Context.RequestData.ReadInt32();
|
||||
Params.Unknown8 = Context.RequestData.ReadInt32();
|
||||
Params.MixCount = Context.RequestData.ReadInt32();
|
||||
Params.VoiceCount = Context.RequestData.ReadInt32();
|
||||
Params.SinkCount = Context.RequestData.ReadInt32();
|
||||
Params.EffectCount = Context.RequestData.ReadInt32();
|
||||
Params.PerformanceManagerCount = Context.RequestData.ReadInt32();
|
||||
Params.VoiceDropEnable = Context.RequestData.ReadInt32();
|
||||
Params.SplitterCount = Context.RequestData.ReadInt32();
|
||||
Params.SplitterDestinationDataCount = Context.RequestData.ReadInt32();
|
||||
Params.Unknown2C = Context.RequestData.ReadInt32();
|
||||
Params.Revision = Context.RequestData.ReadInt32();
|
||||
Params.SampleRate = context.RequestData.ReadInt32();
|
||||
Params.SampleCount = context.RequestData.ReadInt32();
|
||||
Params.Unknown8 = context.RequestData.ReadInt32();
|
||||
Params.MixCount = context.RequestData.ReadInt32();
|
||||
Params.VoiceCount = context.RequestData.ReadInt32();
|
||||
Params.SinkCount = context.RequestData.ReadInt32();
|
||||
Params.EffectCount = context.RequestData.ReadInt32();
|
||||
Params.PerformanceManagerCount = context.RequestData.ReadInt32();
|
||||
Params.VoiceDropEnable = context.RequestData.ReadInt32();
|
||||
Params.SplitterCount = context.RequestData.ReadInt32();
|
||||
Params.SplitterDestinationDataCount = context.RequestData.ReadInt32();
|
||||
Params.Unknown2C = context.RequestData.ReadInt32();
|
||||
Params.Revision = context.RequestData.ReadInt32();
|
||||
|
||||
return Params;
|
||||
}
|
||||
|
||||
private static int NodeStatesGetWorkBufferSize(int Value)
|
||||
private static int NodeStatesGetWorkBufferSize(int value)
|
||||
{
|
||||
int Result = IntUtils.AlignUp(Value, 64);
|
||||
int result = IntUtils.AlignUp(value, 64);
|
||||
|
||||
if (Result < 0)
|
||||
if (result < 0)
|
||||
{
|
||||
Result |= 7;
|
||||
result |= 7;
|
||||
}
|
||||
|
||||
return 4 * (Value * Value) + 0x12 * Value + 2 * (Result / 8);
|
||||
return 4 * (value * value) + 0x12 * value + 2 * (result / 8);
|
||||
}
|
||||
|
||||
private static int EdgeMatrixGetWorkBufferSize(int Value)
|
||||
private static int EdgeMatrixGetWorkBufferSize(int value)
|
||||
{
|
||||
int Result = IntUtils.AlignUp(Value * Value, 64);
|
||||
int result = IntUtils.AlignUp(value * value, 64);
|
||||
|
||||
if (Result < 0)
|
||||
if (result < 0)
|
||||
{
|
||||
Result |= 7;
|
||||
result |= 7;
|
||||
}
|
||||
|
||||
return Result / 8;
|
||||
return result / 8;
|
||||
}
|
||||
|
||||
// GetAudioDeviceService(nn::applet::AppletResourceUserId) -> object<nn::audio::detail::IAudioDevice>
|
||||
public long GetAudioDeviceService(ServiceCtx Context)
|
||||
public long GetAudioDeviceService(ServiceCtx context)
|
||||
{
|
||||
long AppletResourceUserId = Context.RequestData.ReadInt64();
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
MakeObject(Context, new IAudioDevice(Context.Device.System));
|
||||
MakeObject(context, new IAudioDevice(context.Device.System));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// GetAudioDeviceServiceWithRevisionInfo(nn::applet::AppletResourceUserId, u32) -> object<nn::audio::detail::IAudioDevice>
|
||||
private long GetAudioDeviceServiceWithRevisionInfo(ServiceCtx Context)
|
||||
private long GetAudioDeviceServiceWithRevisionInfo(ServiceCtx context)
|
||||
{
|
||||
long AppletResourceUserId = Context.RequestData.ReadInt64();
|
||||
int RevisionInfo = Context.RequestData.ReadInt32();
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
int revisionInfo = context.RequestData.ReadInt32();
|
||||
|
||||
Logger.PrintStub(LogClass.ServiceAudio, $"Stubbed. AppletResourceUserId: {AppletResourceUserId} - " +
|
||||
$"RevisionInfo: {RevisionInfo}");
|
||||
Logger.PrintStub(LogClass.ServiceAudio, $"Stubbed. AppletResourceUserId: {appletResourceUserId} - " +
|
||||
$"RevisionInfo: {revisionInfo}");
|
||||
|
||||
return GetAudioDeviceService(Context);
|
||||
return GetAudioDeviceService(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,80 +10,80 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
{
|
||||
private const int FixedSampleRate = 48000;
|
||||
|
||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||
private Dictionary<int, ServiceProcessRequest> _commands;
|
||||
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
|
||||
|
||||
private int SampleRate;
|
||||
private int ChannelsCount;
|
||||
private int _sampleRate;
|
||||
private int _channelsCount;
|
||||
|
||||
private OpusDecoder Decoder;
|
||||
private OpusDecoder _decoder;
|
||||
|
||||
public IHardwareOpusDecoder(int SampleRate, int ChannelsCount)
|
||||
public IHardwareOpusDecoder(int sampleRate, int channelsCount)
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
_commands = new Dictionary<int, ServiceProcessRequest>
|
||||
{
|
||||
{ 0, DecodeInterleaved },
|
||||
{ 4, DecodeInterleavedWithPerf }
|
||||
};
|
||||
|
||||
this.SampleRate = SampleRate;
|
||||
this.ChannelsCount = ChannelsCount;
|
||||
_sampleRate = sampleRate;
|
||||
_channelsCount = channelsCount;
|
||||
|
||||
Decoder = new OpusDecoder(FixedSampleRate, ChannelsCount);
|
||||
_decoder = new OpusDecoder(FixedSampleRate, channelsCount);
|
||||
}
|
||||
|
||||
public long DecodeInterleavedWithPerf(ServiceCtx Context)
|
||||
public long DecodeInterleavedWithPerf(ServiceCtx context)
|
||||
{
|
||||
long Result = DecodeInterleaved(Context);
|
||||
long result = DecodeInterleaved(context);
|
||||
|
||||
//TODO: Figure out what this value is.
|
||||
//According to switchbrew, it is now used.
|
||||
Context.ResponseData.Write(0L);
|
||||
context.ResponseData.Write(0L);
|
||||
|
||||
return Result;
|
||||
return result;
|
||||
}
|
||||
|
||||
public long DecodeInterleaved(ServiceCtx Context)
|
||||
public long DecodeInterleaved(ServiceCtx context)
|
||||
{
|
||||
long InPosition = Context.Request.SendBuff[0].Position;
|
||||
long InSize = Context.Request.SendBuff[0].Size;
|
||||
long inPosition = context.Request.SendBuff[0].Position;
|
||||
long inSize = context.Request.SendBuff[0].Size;
|
||||
|
||||
if (InSize < 8)
|
||||
if (inSize < 8)
|
||||
{
|
||||
return MakeError(ErrorModule.Audio, AudErr.OpusInvalidInput);
|
||||
}
|
||||
|
||||
long OutPosition = Context.Request.ReceiveBuff[0].Position;
|
||||
long OutSize = Context.Request.ReceiveBuff[0].Size;
|
||||
long outPosition = context.Request.ReceiveBuff[0].Position;
|
||||
long outSize = context.Request.ReceiveBuff[0].Size;
|
||||
|
||||
byte[] OpusData = Context.Memory.ReadBytes(InPosition, InSize);
|
||||
byte[] opusData = context.Memory.ReadBytes(inPosition, inSize);
|
||||
|
||||
int Processed = ((OpusData[0] << 24) |
|
||||
(OpusData[1] << 16) |
|
||||
(OpusData[2] << 8) |
|
||||
(OpusData[3] << 0)) + 8;
|
||||
int processed = ((opusData[0] << 24) |
|
||||
(opusData[1] << 16) |
|
||||
(opusData[2] << 8) |
|
||||
(opusData[3] << 0)) + 8;
|
||||
|
||||
if ((uint)Processed > (ulong)InSize)
|
||||
if ((uint)processed > (ulong)inSize)
|
||||
{
|
||||
return MakeError(ErrorModule.Audio, AudErr.OpusInvalidInput);
|
||||
}
|
||||
|
||||
short[] Pcm = new short[OutSize / 2];
|
||||
short[] pcm = new short[outSize / 2];
|
||||
|
||||
int FrameSize = Pcm.Length / (ChannelsCount * 2);
|
||||
int frameSize = pcm.Length / (_channelsCount * 2);
|
||||
|
||||
int Samples = Decoder.Decode(OpusData, 0, OpusData.Length, Pcm, 0, FrameSize);
|
||||
int samples = _decoder.Decode(opusData, 0, opusData.Length, pcm, 0, frameSize);
|
||||
|
||||
foreach (short Sample in Pcm)
|
||||
foreach (short sample in pcm)
|
||||
{
|
||||
Context.Memory.WriteInt16(OutPosition, Sample);
|
||||
context.Memory.WriteInt16(outPosition, sample);
|
||||
|
||||
OutPosition += 2;
|
||||
outPosition += 2;
|
||||
}
|
||||
|
||||
Context.ResponseData.Write(Processed);
|
||||
Context.ResponseData.Write(Samples);
|
||||
context.ResponseData.Write(processed);
|
||||
context.ResponseData.Write(samples);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,68 +5,68 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
|||
{
|
||||
class IHardwareOpusDecoderManager : IpcService
|
||||
{
|
||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||
private Dictionary<int, ServiceProcessRequest> _commands;
|
||||
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
|
||||
|
||||
public IHardwareOpusDecoderManager()
|
||||
{
|
||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||
_commands = new Dictionary<int, ServiceProcessRequest>
|
||||
{
|
||||
{ 0, Initialize },
|
||||
{ 1, GetWorkBufferSize }
|
||||
};
|
||||
}
|
||||
|
||||
public long Initialize(ServiceCtx Context)
|
||||
public long Initialize(ServiceCtx context)
|
||||
{
|
||||
int SampleRate = Context.RequestData.ReadInt32();
|
||||
int ChannelsCount = Context.RequestData.ReadInt32();
|
||||
int sampleRate = context.RequestData.ReadInt32();
|
||||
int channelsCount = context.RequestData.ReadInt32();
|
||||
|
||||
MakeObject(Context, new IHardwareOpusDecoder(SampleRate, ChannelsCount));
|
||||
MakeObject(context, new IHardwareOpusDecoder(sampleRate, channelsCount));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long GetWorkBufferSize(ServiceCtx Context)
|
||||
public long GetWorkBufferSize(ServiceCtx context)
|
||||
{
|
||||
//Note: The sample rate is ignored because it is fixed to 48KHz.
|
||||
int SampleRate = Context.RequestData.ReadInt32();
|
||||
int ChannelsCount = Context.RequestData.ReadInt32();
|
||||
int sampleRate = context.RequestData.ReadInt32();
|
||||
int channelsCount = context.RequestData.ReadInt32();
|
||||
|
||||
Context.ResponseData.Write(GetOpusDecoderSize(ChannelsCount));
|
||||
context.ResponseData.Write(GetOpusDecoderSize(channelsCount));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int GetOpusDecoderSize(int ChannelsCount)
|
||||
private static int GetOpusDecoderSize(int channelsCount)
|
||||
{
|
||||
const int SilkDecoderSize = 0x2198;
|
||||
const int silkDecoderSize = 0x2198;
|
||||
|
||||
if (ChannelsCount < 1 || ChannelsCount > 2)
|
||||
if (channelsCount < 1 || channelsCount > 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CeltDecoderSize = GetCeltDecoderSize(ChannelsCount);
|
||||
int celtDecoderSize = GetCeltDecoderSize(channelsCount);
|
||||
|
||||
int OpusDecoderSize = (ChannelsCount * 0x800 + 0x4807) & -0x800 | 0x50;
|
||||
int opusDecoderSize = (channelsCount * 0x800 + 0x4807) & -0x800 | 0x50;
|
||||
|
||||
return OpusDecoderSize + SilkDecoderSize + CeltDecoderSize;
|
||||
return opusDecoderSize + silkDecoderSize + celtDecoderSize;
|
||||
}
|
||||
|
||||
private static int GetCeltDecoderSize(int ChannelsCount)
|
||||
private static int GetCeltDecoderSize(int channelsCount)
|
||||
{
|
||||
const int DecodeBufferSize = 0x2030;
|
||||
const int CeltDecoderSize = 0x58;
|
||||
const int CeltSigSize = 0x4;
|
||||
const int Overlap = 120;
|
||||
const int EBandsCount = 21;
|
||||
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;
|
||||
return (decodeBufferSize + overlap * 4) * channelsCount +
|
||||
eBandsCount * 16 +
|
||||
celtDecoderSize +
|
||||
celtSigSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue