예제 #1
0
        // RequestUpdateAudioRenderer(buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 5>)
        // -> (buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 6>, buffer<nn::audio::detail::AudioRendererUpdateDataHeader, 6>)
        public ResultCode RequestUpdateAudioRenderer(ServiceCtx context)
        {
            long outputPosition = context.Request.ReceiveBuff[0].Position;
            long outputSize     = context.Request.ReceiveBuff[0].Size;

            MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);

            long inputPosition = context.Request.SendBuff[0].Position;

            StructReader reader = new StructReader(context.Memory, inputPosition);
            StructWriter writer = new StructWriter(context.Memory, outputPosition);

            UpdateDataHeader inputHeader = reader.Read <UpdateDataHeader>();

            BehaviorInfo behaviorInfo = new BehaviorInfo();

            behaviorInfo.SetUserLibRevision(inputHeader.Revision);

            reader.Read <BehaviorIn>(inputHeader.BehaviorSize);

            MemoryPoolIn[] memoryPoolsIn = reader.Read <MemoryPoolIn>(inputHeader.MemoryPoolSize);

            for (int index = 0; index < memoryPoolsIn.Length; index++)
            {
                MemoryPoolIn memoryPool = memoryPoolsIn[index];

                if (memoryPool.State == MemoryPoolState.RequestAttach)
                {
                    _memoryPools[index].OutStatus.State = MemoryPoolState.Attached;
                }
                else if (memoryPool.State == MemoryPoolState.RequestDetach)
                {
                    _memoryPools[index].OutStatus.State = MemoryPoolState.Detached;
                }
            }

            reader.Read <VoiceChannelResourceIn>(inputHeader.VoiceResourceSize);

            VoiceIn[] voicesIn = reader.Read <VoiceIn>(inputHeader.VoiceSize);

            for (int index = 0; index < voicesIn.Length; index++)
            {
                VoiceIn voice = voicesIn[index];

                VoiceContext voiceCtx = _voices[index];

                voiceCtx.SetAcquireState(voice.Acquired != 0);

                if (voice.Acquired == 0)
                {
                    continue;
                }

                if (voice.FirstUpdate != 0)
                {
                    voiceCtx.AdpcmCtx = GetAdpcmDecoderContext(
                        voice.AdpcmCoeffsPosition,
                        voice.AdpcmCoeffsSize);

                    voiceCtx.SampleFormat  = voice.SampleFormat;
                    voiceCtx.SampleRate    = voice.SampleRate;
                    voiceCtx.ChannelsCount = voice.ChannelsCount;

                    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;
            }

            EffectIn[] effectsIn = reader.Read <EffectIn>(inputHeader.EffectSize);

            for (int index = 0; index < effectsIn.Length; index++)
            {
                if (effectsIn[index].IsNew != 0)
                {
                    _effects[index].OutStatus.State = EffectState.New;
                }
            }

            UpdateAudio();

            UpdateDataHeader outputHeader = new UpdateDataHeader();

            int updateHeaderSize = Marshal.SizeOf <UpdateDataHeader>();

            outputHeader.Revision               = AudioRendererConsts.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;

            if (behaviorInfo.IsElapsedFrameCountSupported())
            {
                outputHeader.ElapsedFrameCountInfoSize = 0x10;
            }

            outputHeader.TotalSize = updateHeaderSize +
                                     outputHeader.BehaviorSize +
                                     outputHeader.MemoryPoolSize +
                                     outputHeader.VoiceSize +
                                     outputHeader.EffectSize +
                                     outputHeader.SinkSize +
                                     outputHeader.PerformanceManagerSize +
                                     outputHeader.ElapsedFrameCountInfoSize;

            writer.Write(outputHeader);

            foreach (MemoryPoolContext memoryPool in _memoryPools)
            {
                writer.Write(memoryPool.OutStatus);
            }

            foreach (VoiceContext voice in _voices)
            {
                writer.Write(voice.OutStatus);
            }

            foreach (EffectContext effect in _effects)
            {
                writer.Write(effect.OutStatus);
            }

            writer.SkipBytes(_params.SinkCount * 0x20);
            writer.SkipBytes(outputHeader.PerformanceManagerSize);
            writer.SkipBytes(outputHeader.BehaviorSize);

            if (behaviorInfo.IsElapsedFrameCountSupported())
            {
                writer.Write(new RendererInfoOut
                {
                    ElapsedFrameCount = _elapsedFrameCount
                });
            }

            return(ResultCode.Success);
        }