Skip to content

Commit 436ec17

Browse files
committed
Fixing potential invalid memory access in Gen2DFTLib
1 parent 27397c0 commit 436ec17

File tree

1 file changed

+16
-20
lines changed

1 file changed

+16
-20
lines changed

Gen2DFTLib/Gen2DFT.cs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
using ColorChord.NET.NoteFinder;
2+
using System;
23
using System.Runtime.InteropServices;
34

45
namespace Gen2DFTLib;
56

7+
/// <summary> Provides the core DFT algorithm used in the Gen2NoteFinder in ColorChord.NET for use in other software. </summary>
8+
/// <remarks> Make sure to initialize with <see cref="Init(uint, uint, float, float)"/> before attempting to use. </remarks>
69
public static unsafe class Gen2DFT
710
{
811
private static Gen2NoteFinderDFT DFT;
12+
private static GCHandle BinMagnitudesHandle, BinFrequenciesHandle, BinWidthsHandle;
913

1014
/// <summary> Prepares the DFT for use, initializing internal data structures. </summary>
1115
/// <param name="octaveCount"> The number of octaves to analyze </param>
@@ -16,6 +20,9 @@ public static unsafe class Gen2DFT
1620
public static void Init(uint octaveCount, uint sampleRate, float startFrequency, float loudnessCorrection)
1721
{
1822
DFT = new(octaveCount, sampleRate, startFrequency, loudnessCorrection, null);
23+
BinMagnitudesHandle = GCHandle.Alloc(DFT.RawBinMagnitudes, GCHandleType.Pinned);
24+
BinFrequenciesHandle = GCHandle.Alloc(DFT.RawBinFrequencies, GCHandleType.Pinned);
25+
BinWidthsHandle = GCHandle.Alloc(DFT.RawBinWidths, GCHandleType.Pinned);
1926
}
2027

2128
/// <summary> Processes the given audio data into the DFT. </summary>
@@ -29,12 +36,9 @@ public static void AddAudioData(short* newData, uint count)
2936
}
3037

3138
/// <summary> Updates the output values for reading based on the audio data that has been added until now. </summary>
32-
/// <remarks> Read the audio data using <see cref="GetBinMagnitudes"/>. </remarks>
39+
/// <remarks> Read the output data using <see cref="GetBinMagnitudes"/>. </remarks>
3340
[UnmanagedCallersOnly(EntryPoint = "Gen2DFT_CalculateOutput")]
34-
public static void CalculateOutput()
35-
{
36-
DFT.CalculateOutput();
37-
}
41+
public static void CalculateOutput() => DFT.CalculateOutput();
3842

3943
/// <summary> Gets the number of output bins per octave. </summary>
4044
[UnmanagedCallersOnly(EntryPoint = "Gen2DFT_GetBinsPerOctave")]
@@ -45,26 +49,18 @@ public static void CalculateOutput()
4549
public static uint GetBinCount() => DFT.BinCount;
4650

4751
/// <summary> Gets the current DFT output data. Make sure to call <see cref="CalculateOutput"/> before this. </summary>
48-
/// <returns> The raw magnitudes of each DFT bin, length is <see cref="GetBinCount"/>. </returns>
52+
/// <returns> The raw magnitudes of each DFT bin, array length is <see cref="GetBinCount"/>. This pointer will not change during runtime unless <see cref="Init(uint, uint, float, float)"/> is called again, so it is safe to reuse </returns>
4953
[UnmanagedCallersOnly(EntryPoint = "Gen2DFT_GetBinMagnitudes")]
50-
public static float* GetBinMagnitudes()
51-
{
52-
fixed (float* BinMags = DFT.RawBinMagnitudes) { return BinMags; }
53-
}
54+
public static float* GetBinMagnitudes() => (float*)BinMagnitudesHandle.AddrOfPinnedObject();
5455

5556
/// <summary> Gets the central response frequencies of each DFT bin. </summary>
56-
/// <returns> The frequency of each DFT bin in Hz, length is <see cref="GetBinCount"/>. </returns>
57+
/// <returns> The frequency of each DFT bin in Hz, array length is <see cref="GetBinCount"/>. This pointer will not change during runtime unless <see cref="Init(uint, uint, float, float)"/> is called again, so it is safe to reuse </returns>
5758
[UnmanagedCallersOnly(EntryPoint = "Gen2DFT_GetBinFrequencies")]
58-
public static float* GetBinFrequencies()
59-
{
60-
fixed (float* BinFreqs = DFT.RawBinFrequencies) { return BinFreqs; }
61-
}
59+
public static float* GetBinFrequencies() => (float*)BinFrequenciesHandle.AddrOfPinnedObject();
6260

6361
/// <summary> Gets the sensitivity range width of each bin, in number of bins. </summary>
64-
/// <returns> The width of each bin in number of bins, length is <see cref="GetBinCount"/>. A value of 2 would mean that this bin stops responding to frequencies around the center of the bin above and below (this bin's range = 1, plus 0.5 bins on either side) </returns>
62+
/// <remarks> A value of 2 would mean that this bin stops responding to frequencies around the center of the bin above and below (this bin's range = 1, plus 0.5 bins on either side) </remarks>
63+
/// <returns> The width of each bin in number of bins, array length is <see cref="GetBinCount"/>. This pointer will not change during runtime unless <see cref="Init(uint, uint, float, float)"/> is called again, so it is safe to reuse </returns>
6564
[UnmanagedCallersOnly(EntryPoint = "Gen2DFT_GetBinWidths")]
66-
public static float* GetBinWidths()
67-
{
68-
fixed (float* BinWidths = DFT.RawBinWidths) { return BinWidths; }
69-
}
65+
public static float* GetBinWidths() => (float*)BinWidthsHandle.AddrOfPinnedObject();
7066
}

0 commit comments

Comments
 (0)