Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        /// <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);
            }
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
0
        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;
            }