Skip to content

Use Span<T> for APIs #285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions SFML.Module.props
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@
<PackageReference Include="CSFML" Version="[3.0.0-rc.1, 3.1)" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="System.Memory" Version="4.6.0" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion examples/opengl/OpenGL.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private static void Main()
{
GL.GenTextures(1, out texture);
GL.BindTexture(TextureTarget.Texture2D, texture);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)image.Size.X, (int)image.Size.Y, 0, PixelFormat.Rgba, PixelType.UnsignedByte, image.Pixels);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)image.Size.X, (int)image.Size.Y, 0, PixelFormat.Rgba, PixelType.UnsignedByte, image.Pixels.ToArray());
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
}
Expand Down
4 changes: 2 additions & 2 deletions src/SFML.Audio/EffectProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ namespace SFML.Audio
/// occur.
/// </summary>
////////////////////////////////////////////////////////////
public delegate long EffectProcessor(float[] inputFrames, float[] outputFrames, uint frameChannelCount);
public delegate long EffectProcessor(ReadOnlySpan<float> inputFrames, out uint inputFramesRead, Span<float> outputFrames, out uint outputFramesWritten, uint frameChannelCount);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate long EffectProcessorInternal(IntPtr inputFrames, uint inputFrameCount, IntPtr outputFrames, uint outputFrameCount, uint frameChannelCount);
internal unsafe delegate long EffectProcessorInternal(float* inputFrames, ref uint inputFrameCount, float* outputFrames, ref uint outputFrameCount, uint frameChannelCount);
}
32 changes: 16 additions & 16 deletions src/SFML.Audio/Music.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public Music(string filename) :
/// </summary>
/// <param name="stream">Source stream to read from</param>
////////////////////////////////////////////////////////////
public Music(Stream stream) :
public Music(Stream stream) : // TODO this stream needs to stay alive
base(IntPtr.Zero)
{
_stream = new StreamAdaptor(stream);
Expand All @@ -71,7 +71,7 @@ public Music(Stream stream) :
/// <param name="bytes">Byte array containing the file contents</param>
/// <exception cref="LoadingFailedException" />
////////////////////////////////////////////////////////////
public Music(byte[] bytes) :
public Music(byte[] bytes) : // TODO this memory needs to stay alive
base(IntPtr.Zero)
{
unsafe
Expand Down Expand Up @@ -140,21 +140,21 @@ public Music(byte[] bytes) :
/// position during spatialisation.
/// </summary>
////////////////////////////////////////////////////////////
public SoundChannel[] ChannelMap
public ReadOnlySpan<SoundChannel> ChannelMap
{
get
{
unsafe
{
var channels = sfMusic_getChannelMap(CPointer, out var count);
var arr = new SoundChannel[(int)count];
Array.Resize(ref _channels, (int)count);

for (var i = 0; i < arr.Length; i++)
for (var i = 0; i < _channels.Length; i++)
{
arr[i] = channels[i];
_channels[i] = channels[i];
}

return arr;
return _channels;
}
}
}
Expand Down Expand Up @@ -498,17 +498,16 @@ public TimeSpan LoopPoints
////////////////////////////////////////////////////////////
public void SetEffectProcessor(EffectProcessor effectProcessor)
{
_effectProcessor = (inputFrames, inputFrameCount, outputFrames, outputFrameCount, frameChannelCount) =>
unsafe
{
var inputFramesArray = new float[inputFrameCount];
var outputFramesArray = new float[outputFrameCount];

Marshal.Copy(inputFrames, inputFramesArray, 0, inputFramesArray.Length);
var written = effectProcessor(inputFramesArray, outputFramesArray, frameChannelCount);
Marshal.Copy(outputFramesArray, 0, outputFrames, outputFramesArray.Length);
_effectProcessor = (float* inputFrames, ref uint inputFrameCount, float* outputFrames, ref uint outputFrameCount, uint frameChannelCount) =>
{
var inputBuffer = new ReadOnlySpan<float>(inputFrames, (int)inputFrameCount);
var outputBuffer = new Span<float>(outputFrames, (int)outputFrameCount);

return written;
};
return effectProcessor(inputBuffer, out inputFrameCount, outputBuffer, out outputFrameCount, frameChannelCount);
};
}

sfMusic_setEffectProcessor(CPointer, Marshal.GetFunctionPointerForDelegate(_effectProcessor));
}
Expand Down Expand Up @@ -560,6 +559,7 @@ protected override void Destroy(bool disposing)

private readonly StreamAdaptor _stream;
private EffectProcessorInternal _effectProcessor;
private SoundChannel[] _channels;

/// <summary>
/// Structure defining a Time range.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
Expand All @@ -7,7 +7,7 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Release</Configuration>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<PublishDir>bin\PublishOutput</PublishDir>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion src/SFML.Audio/SFML.Audio.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<SFMLModule>Audio</SFMLModule>
<Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>
Expand Down
17 changes: 8 additions & 9 deletions src/SFML.Audio/Sound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,17 +403,16 @@ public float Attenuation
////////////////////////////////////////////////////////////
public void SetEffectProcessor(EffectProcessor effectProcessor)
{
_effectProcessor = (inputFrames, inputFrameCount, outputFrames, outputFrameCount, frameChannelCount) =>
unsafe
{
var inputFramesArray = new float[inputFrameCount];
var outputFramesArray = new float[outputFrameCount];
_effectProcessor = (float* inputFrames, ref uint inputFrameCount, float* outputFrames, ref uint outputFrameCount, uint frameChannelCount) =>
{
var inputBuffer = new ReadOnlySpan<float>(inputFrames, (int)inputFrameCount);
var outputBuffer = new Span<float>(outputFrames, (int)outputFrameCount);

Marshal.Copy(inputFrames, inputFramesArray, 0, inputFramesArray.Length);
var written = effectProcessor(inputFramesArray, outputFramesArray, frameChannelCount);
Marshal.Copy(outputFramesArray, 0, outputFrames, outputFramesArray.Length);

return written;
};
return effectProcessor(inputBuffer, out inputFrameCount, outputBuffer, out outputFrameCount, frameChannelCount);
};
}

sfSound_setEffectProcessor(CPointer, Marshal.GetFunctionPointerForDelegate(_effectProcessor));
}
Expand Down
28 changes: 17 additions & 11 deletions src/SFML.Audio/SoundBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public SoundBuffer(Stream stream) :
/// <param name="bytes">Byte array containing the file contents</param>
/// <exception cref="LoadingFailedException" />
////////////////////////////////////////////////////////////
public SoundBuffer(byte[] bytes) :
public SoundBuffer(ReadOnlySpan<byte> bytes) :
base(IntPtr.Zero)
{
unsafe
Expand All @@ -96,7 +96,7 @@ public SoundBuffer(byte[] bytes) :
/// <param name="channelMapData">Map of position in sample frame to sound channel</param>
/// <exception cref="LoadingFailedException" />
////////////////////////////////////////////////////////////
public SoundBuffer(short[] samples, uint channelCount, uint sampleRate, SoundChannel[] channelMapData) :
public SoundBuffer(ReadOnlySpan<short> samples, uint channelCount, uint sampleRate, ReadOnlySpan<SoundChannel> channelMapData) :
base(IntPtr.Zero)
{
unsafe
Expand Down Expand Up @@ -172,13 +172,17 @@ public SoundBuffer(SoundBuffer copy) :
/// (sf::Int16).
/// </summary>
////////////////////////////////////////////////////////////
public short[] Samples
public ReadOnlySpan<short> Samples
{
get
{
var samplesArray = new short[sfSoundBuffer_getSampleCount(CPointer)];
Marshal.Copy(sfSoundBuffer_getSamples(CPointer), samplesArray, 0, samplesArray.Length);
return samplesArray;
unsafe
{
// Sample array should remain constant and not get invalidated as a result
var samplesCount = sfSoundBuffer_getSampleCount(CPointer);
var samples = sfSoundBuffer_getSamples(CPointer);
return new ReadOnlySpan<short>(samples.ToPointer(), (int)samplesCount);
}
}
}

Expand All @@ -190,21 +194,21 @@ public short[] Samples
/// position during spatialisation.
/// </summary>
////////////////////////////////////////////////////////////
public virtual SoundChannel[] ChannelMap
public virtual ReadOnlySpan<SoundChannel> ChannelMap
{
get
{
unsafe
{
var channels = sfSoundBuffer_getChannelMap(CPointer, out var count);
var arr = new SoundChannel[(int)count];
Array.Resize(ref _channels, (int)count);

for (var i = 0; i < arr.Length; i++)
for (var i = 0; i < _channels.Length; i++)
{
arr[i] = channels[i];
_channels[i] = channels[i];
}

return arr;
return _channels;
}
}
}
Expand Down Expand Up @@ -236,6 +240,8 @@ public override string ToString()
////////////////////////////////////////////////////////////
protected override void Destroy(bool disposing) => sfSoundBuffer_destroy(CPointer);

private SoundChannel[] _channels;

#region Imports
[DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
private static extern IntPtr sfSoundBuffer_createFromFile(string filename);
Expand Down
8 changes: 6 additions & 2 deletions src/SFML.Audio/SoundBufferRecorder.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;

namespace SFML.Audio
Expand Down Expand Up @@ -59,9 +60,12 @@ protected override bool OnStart()
/// <param name="samples">Array of samples to process</param>
/// <returns>False to stop recording audio data, true to continue</returns>
////////////////////////////////////////////////////////////
protected override bool OnProcessSamples(short[] samples)
protected override bool OnProcessSamples(ReadOnlySpan<short> samples)
{
_samplesArray.AddRange(samples);
for (var i = 0; i < samples.Length; i++)
{
_samplesArray.Add(samples[i]);
}
return true;
}

Expand Down
33 changes: 18 additions & 15 deletions src/SFML.Audio/SoundRecorder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,21 @@ public uint ChannelCount
/// position during spatialisation.
/// </summary>
////////////////////////////////////////////////////////////
public SoundChannel[] ChannelMap
public ReadOnlySpan<SoundChannel> ChannelMap
{
get
{
unsafe
{
var channels = sfSoundRecorder_getChannelMap(CPointer, out var count);
var arr = new SoundChannel[(int)count];
Array.Resize(ref _channels, (int)count);

for (var i = 0; i < arr.Length; i++)
for (var i = 0; i < _channels.Length; i++)
{
arr[i] = channels[i];
_channels[i] = channels[i];
}

return arr;
return _channels;
}
}
}
Expand Down Expand Up @@ -173,7 +173,7 @@ protected virtual bool OnStart() =>
/// <param name="samples">Array of samples to process</param>
/// <returns>False to stop recording audio data, true to continue</returns>
////////////////////////////////////////////////////////////
protected abstract bool OnProcessSamples(short[] samples);
protected abstract bool OnProcessSamples(ReadOnlySpan<short> samples);

////////////////////////////////////////////////////////////
/// <summary>
Expand All @@ -195,23 +195,25 @@ protected virtual void OnStop()
/// Get the list of the names of all available audio capture devices
/// </summary>
////////////////////////////////////////////////////////////
public static string[] AvailableDevices
public static ReadOnlySpan<string> AvailableDevices
{
get
{
unsafe
{
var devicesPtr = sfSoundRecorder_getAvailableDevices(out var count);
var devices = new string[(int)count];
for (var i = 0; i < (int)count; ++i)
Array.Resize(ref _availableDevices, (int)count);

for (var i = 0; i < _availableDevices.Length; i++)
{
devices[i] = Marshal.PtrToStringAnsi(devicesPtr[i]);
_availableDevices[i] = Marshal.PtrToStringAnsi(devicesPtr[i]);
}

return devices;
return _availableDevices;
}
}
}
private static string[] _availableDevices;

////////////////////////////////////////////////////////////
/// <summary>
Expand Down Expand Up @@ -267,10 +269,10 @@ public static string[] AvailableDevices
////////////////////////////////////////////////////////////
private bool ProcessSamples(IntPtr samples, UIntPtr nbSamples, IntPtr userData)
{
var samplesArray = new short[(int)nbSamples];
Marshal.Copy(samples, samplesArray, 0, samplesArray.Length);

return OnProcessSamples(samplesArray);
unsafe
{
return OnProcessSamples(new ReadOnlySpan<short>((void*)samples, (int)nbSamples));
}
}

////////////////////////////////////////////////////////////
Expand All @@ -294,6 +296,7 @@ private bool ProcessSamples(IntPtr samples, UIntPtr nbSamples, IntPtr userData)
private readonly StartCallback _startCallback;
private readonly ProcessCallback _processCallback;
private readonly StopCallback _stopCallback;
private SoundChannel[] _channels;

#region Imports
[DllImport(CSFML.Audio, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
Expand Down
Loading
Loading