public StateUpdater(ReadOnlyMemory <byte> input, Memory <byte> output, uint processHandle, BehaviourContext behaviourContext) { _input = input; _inputOrigin = _input; _output = output; _outputOrigin = _output; _processHandle = processHandle; _behaviourContext = behaviourContext; _inputHeader = SpanIOHelper.Read <UpdateDataHeader>(ref _input); _outputHeader = SpanMemoryManager <UpdateDataHeader> .Cast(_output.Slice(0, Unsafe.SizeOf <UpdateDataHeader>())); OutputHeader.Initialize(_behaviourContext.UserRevision); _output = _output.Slice(Unsafe.SizeOf <UpdateDataHeader>()); }
public AudioRenderSystem(AudioRendererManager manager, IWritableEvent systemEvent) { _manager = manager; _terminationEvent = new ManualResetEvent(false); _dspMemoryPoolState = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp); _voiceContext = new VoiceContext(); _mixContext = new MixContext(); _sinkContext = new SinkContext(); _splitterContext = new SplitterContext(); _effectContext = new EffectContext(); _commandProcessingTimeEstimator = null; _systemEvent = systemEvent; _behaviourContext = new BehaviourContext(); _totalElapsedTicksUpdating = 0; _sessionId = 0; }
public ResultCode UpdateBehaviourContext() { BehaviourParameter parameter = SpanIOHelper.Read <BehaviourParameter>(ref _input); if (!BehaviourContext.CheckValidRevision(parameter.UserRevision) || parameter.UserRevision != _behaviourContext.UserRevision) { return(ResultCode.InvalidUpdateInfo); } _behaviourContext.ClearError(); _behaviourContext.UpdateFlags(parameter.Flags); if (_inputHeader.BehaviourSize != Unsafe.SizeOf <BehaviourParameter>()) { return(ResultCode.InvalidUpdateInfo); } return(ResultCode.Success); }
public ResultCode Initialize(ref AudioRendererConfiguration parameter, uint processHandle, CpuAddress workBuffer, ulong workBufferSize, int sessionId, ulong appletResourceId, IVirtualMemoryManager memoryManager) { if (!BehaviourContext.CheckValidRevision(parameter.Revision)) { return(ResultCode.OperationFailed); } if (GetWorkBufferSize(ref parameter) > workBufferSize) { return(ResultCode.WorkBufferTooSmall); } Debug.Assert(parameter.RenderingDevice == AudioRendererRenderingDevice.Dsp && parameter.ExecutionMode == AudioRendererExecutionMode.Auto); Logger.Info?.Print(LogClass.AudioRenderer, $"Initializing with REV{BehaviourContext.GetRevisionNumber(parameter.Revision)}"); _behaviourContext.SetUserRevision(parameter.Revision); _sampleRate = parameter.SampleRate; _sampleCount = parameter.SampleCount; _mixBufferCount = parameter.MixBufferCount; _voiceChannelCountMax = Constants.VoiceChannelCountMax; _upsamplerCount = parameter.SinkCount + parameter.SubMixBufferCount; _appletResourceId = appletResourceId; _memoryPoolCount = parameter.EffectCount + parameter.VoiceCount * Constants.VoiceWaveBufferCount; _executionMode = parameter.ExecutionMode; _sessionId = sessionId; MemoryManager = memoryManager; if (memoryManager is IRefCounted rc) { rc.IncrementReferenceCount(); } WorkBufferAllocator workBufferAllocator; _workBufferRegion = MemoryManager.GetWritableRegion(workBuffer, (int)workBufferSize); _workBufferRegion.Memory.Span.Fill(0); _workBufferMemoryPin = _workBufferRegion.Memory.Pin(); workBufferAllocator = new WorkBufferAllocator(_workBufferRegion.Memory); PoolMapper poolMapper = new PoolMapper(processHandle, false); poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize); _mixBuffer = workBufferAllocator.Allocate <float>(_sampleCount * (_voiceChannelCountMax + _mixBufferCount), 0x10); if (_mixBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } Memory <float> upSamplerWorkBuffer = workBufferAllocator.Allocate <float>(Constants.TargetSampleCount * (_voiceChannelCountMax + _mixBufferCount) * _upsamplerCount, 0x10); if (upSamplerWorkBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } _depopBuffer = workBufferAllocator.Allocate <float>((ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment); if (_depopBuffer.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } // Invalidate DSP cache on what was currently allocated with workBuffer. AudioProcessorMemoryManager.InvalidateDspCache(_dspMemoryPoolState.Translate(workBuffer, workBufferAllocator.Offset), workBufferAllocator.Offset); Debug.Assert((workBufferAllocator.Offset % Constants.BufferAlignment) == 0); Memory <VoiceState> voices = workBufferAllocator.Allocate <VoiceState>(parameter.VoiceCount, VoiceState.Alignment); if (voices.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } foreach (ref VoiceState voice in voices.Span) { voice.Initialize(); } // A pain to handle as we can't have VoiceState*, use indices to be a bit more safe Memory <int> sortedVoices = workBufferAllocator.Allocate <int>(parameter.VoiceCount, 0x10); if (sortedVoices.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } // Clear memory (use -1 as it's an invalid index) sortedVoices.Span.Fill(-1); Memory <VoiceChannelResource> voiceChannelResources = workBufferAllocator.Allocate <VoiceChannelResource>(parameter.VoiceCount, VoiceChannelResource.Alignment); if (voiceChannelResources.IsEmpty) { return(ResultCode.WorkBufferTooSmall); } for (uint id = 0; id < voiceChannelResources.Length; id++) { ref VoiceChannelResource voiceChannelResource = ref voiceChannelResources.Span[(int)id]; voiceChannelResource.Id = id; voiceChannelResource.IsUsed = false; }