| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- using System;
- using System.Numerics;
- using System.Runtime.CompilerServices;
- namespace Ryujinx.Audio.Renderer.Dsp
- {
- public static class PcmHelper
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int GetCountToDecode(int startSampleOffset, int endSampleOffset, int offset, int count)
- {
- return Math.Min(count, endSampleOffset - startSampleOffset - offset);
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong GetBufferOffset<T>(int startSampleOffset, int offset, int channelCount) where T : unmanaged
- {
- return (ulong)(Unsafe.SizeOf<T>() * channelCount * (startSampleOffset + offset));
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int GetBufferSize<T>(int startSampleOffset, int endSampleOffset, int offset, int count) where T : unmanaged
- {
- return GetCountToDecode(startSampleOffset, endSampleOffset, offset, count) * Unsafe.SizeOf<T>();
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static float ConvertSampleToPcmFloat(short sample)
- {
- return (float)sample / short.MaxValue;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static short ConvertSampleToPcmInt16(float sample)
- {
- return Saturate(sample * short.MaxValue);
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static TOutput ConvertSample<TInput, TOutput>(TInput value) where TInput: INumber<TInput>, IMinMaxValue<TInput> where TOutput : INumber<TOutput>, IMinMaxValue<TOutput>
- {
- TInput conversionRate = TInput.CreateSaturating(TOutput.MaxValue / TOutput.CreateSaturating(TInput.MaxValue));
- return TOutput.CreateSaturating(value * conversionRate);
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Convert<TInput, TOutput>(Span<TOutput> output, ReadOnlySpan<TInput> input) where TInput : INumber<TInput>, IMinMaxValue<TInput> where TOutput : INumber<TOutput>, IMinMaxValue<TOutput>
- {
- for (int i = 0; i < input.Length; i++)
- {
- output[i] = ConvertSample<TInput, TOutput>(input[i]);
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void ConvertSampleToPcmFloat(Span<float> output, ReadOnlySpan<short> input)
- {
- for (int i = 0; i < input.Length; i++)
- {
- output[i] = ConvertSampleToPcmFloat(input[i]);
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int Decode(Span<short> output, ReadOnlySpan<short> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount)
- {
- if (input.IsEmpty || endSampleOffset < startSampleOffset)
- {
- return 0;
- }
- int decodedCount = input.Length / channelCount;
- for (int i = 0; i < decodedCount; i++)
- {
- output[i] = input[i * channelCount + channelIndex];
- }
- return decodedCount;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int Decode(Span<short> output, ReadOnlySpan<float> input, int startSampleOffset, int endSampleOffset, int channelIndex, int channelCount)
- {
- if (input.IsEmpty || endSampleOffset < startSampleOffset)
- {
- return 0;
- }
- int decodedCount = input.Length / channelCount;
- for (int i = 0; i < decodedCount; i++)
- {
- output[i] = ConvertSampleToPcmInt16(input[i * channelCount + channelIndex]);
- }
- return decodedCount;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static short Saturate(float value)
- {
- if (value > short.MaxValue)
- {
- return short.MaxValue;
- }
- if (value < short.MinValue)
- {
- return short.MinValue;
- }
- return (short)value;
- }
- }
- }
|