/// <summary> /// Map the <see cref="MemoryPoolState"/> on the <see cref="Dsp.AudioProcessor"/>. /// </summary> /// <param name="memoryPool">The <see cref="MemoryPoolState"/> to map.</param> /// <returns>Returns the DSP address mapped.</returns> public DspAddress Map(ref MemoryPoolState memoryPool) { DspAddress result = AudioProcessorMemoryManager.Map(GetProcessHandle(ref memoryPool), memoryPool.CpuAddress, memoryPool.Size); if (result != 0) { memoryPool.DspAddress = result; } return(result); }
/// <summary> /// Unmap the <see cref="MemoryPoolState"/> from the <see cref="Dsp.AudioProcessor"/>. /// </summary> /// <param name="memoryPool">The <see cref="MemoryPoolState"/> to unmap.</param> /// <returns>Returns true if unmapped.</returns> public bool Unmap(ref MemoryPoolState memoryPool) { if (memoryPool.IsUsed) { return(false); } AudioProcessorMemoryManager.Unmap(GetProcessHandle(ref memoryPool), memoryPool.CpuAddress, memoryPool.Size); memoryPool.SetCpuAddress(0, 0); memoryPool.DspAddress = 0; return(true); }
/// <summary> /// Force unmap the given <see cref="AddressInfo"/>. /// </summary> /// <param name="addressInfo">The <see cref="AddressInfo"/> to force unmap</param> public void ForceUnmap(ref AddressInfo addressInfo) { if (_isForceMapEnabled) { Span <MemoryPoolState> memoryPool = FindMemoryPool(addressInfo.CpuAddress, addressInfo.Size); if (!memoryPool.IsEmpty) { AudioProcessorMemoryManager.Unmap(_processHandle, memoryPool[0].CpuAddress, memoryPool[0].Size); return; } AudioProcessorMemoryManager.Unmap(_processHandle, addressInfo.CpuAddress, 0); } }
/// <summary> /// Get the first work buffer DSP address. /// </summary> /// <returns>The first work buffer DSP address.</returns> protected DspAddress GetSingleBuffer() { if (IsEnabled) { return(WorkBuffers[0].GetReference(true)); } if (UsageState != UsageState.Disabled) { DspAddress address = WorkBuffers[0].GetReference(false); ulong size = WorkBuffers[0].Size; if (address != 0 && size != 0) { AudioProcessorMemoryManager.InvalidateDataCache(address, size); } } return(0); }
/// <summary> /// Map the <see cref="AddressInfo"/> to the <see cref="Dsp.AudioProcessor"/>. /// </summary> /// <param name="addressInfo">The <see cref="AddressInfo"/> to map.</param> /// <returns>Returns true if mapping was performed.</returns> private bool AssignDspAddress(ref AddressInfo addressInfo) { if (addressInfo.CpuAddress == 0) { return(false); } if (_memoryPools.Length > 0) { Span <MemoryPoolState> memoryPool = FindMemoryPool(addressInfo.CpuAddress, addressInfo.Size); if (!memoryPool.IsEmpty) { addressInfo.SetupMemoryPool(memoryPool); return(true); } } if (_isForceMapEnabled) { DspAddress dspAddress = AudioProcessorMemoryManager.Map(_processHandle, addressInfo.CpuAddress, addressInfo.Size); addressInfo.ForceMappedDspAddress = dspAddress; AudioProcessorMemoryManager.Map(_processHandle, addressInfo.CpuAddress, addressInfo.Size); } else { unsafe { addressInfo.SetupMemoryPool(MemoryPoolState.Null); } } return(false); }
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; }