@@ -17,7 +17,7 @@ public class WavTools
1717 /// <param name="l">Output of left channel</param>
1818 /// <param name="r">Output of right channel</param>
1919 /// <returns>Details of wav file</returns>
20- public WavHeader ? ReadWav ( string filename , out float [ ] ? l , out float [ ] ? r )
20+ public static WavHeader ? ReadWav ( string filename , out float [ ] ? l , out float [ ] ? r )
2121 {
2222 l = r = null ;
2323
@@ -161,7 +161,7 @@ public class WavTools
161161 /// <param name="filename">Path to file name</param>
162162 /// <param name="m">Output of left channel</param>
163163 /// <returns>Details of wav file</returns>
164- public WavHeader ? ReadWav ( string filename , out float [ ] ? m )
164+ public static WavHeader ? ReadWav ( string filename , out float [ ] ? m )
165165 {
166166 m = null ;
167167
@@ -290,5 +290,86 @@ public class WavTools
290290 return null ;
291291 }
292292 }
293+
294+ /// <summary>
295+ /// Source: https://gist.github.com/adrianseeley/264417d295ccd006e7fd
296+ /// </summary>
297+ /// <param name="array">Input data</param>
298+ /// <param name="length">Length of return array</param>
299+ /// <returns></returns>
300+ public static float [ ] Downsample ( float [ ] array , int length )
301+ {
302+ int insert = 0 ;
303+ float [ ] window = new float [ length ] ;
304+ float [ ] windowX = new float [ length ] ;
305+ int bucketSizeLessStartAndEnd = length - 2 ;
306+
307+ float bucketSize = ( float ) ( array . Length - 2 ) / bucketSizeLessStartAndEnd ;
308+ int a = 0 ;
309+ int nextA = 0 ;
310+ int maxAreaPointX = 0 ;
311+ float maxAreaPointY = 0f ;
312+ window [ insert ] = array [ a ] ; // Always add the first point
313+ windowX [ insert ] = 0 ;
314+ insert ++ ;
315+ for ( int i = 0 ; i < bucketSizeLessStartAndEnd ; i ++ )
316+ {
317+ // Calculate point average for next bucket (containing c)
318+ float avgX = 0 ;
319+ float avgY = 0 ;
320+ int start = ( int ) ( Math . Floor ( ( i + 1 ) * bucketSize ) + 1 ) ;
321+ int end = ( int ) ( Math . Floor ( ( i + 2 ) * bucketSize ) + 1 ) ;
322+ if ( end >= array . Length )
323+ {
324+ end = array . Length ;
325+ }
326+ int span = end - start ;
327+ for ( ; start < end ; start ++ )
328+ {
329+ avgX += start ;
330+ avgY += array [ start ] ;
331+ }
332+ avgX /= span ;
333+ avgY /= span ;
334+
335+ // Get the range for this bucket
336+ int bucketStart = ( int ) ( Math . Floor ( ( i + 0 ) * bucketSize ) + 1 ) ;
337+ int bucketEnd = ( int ) ( Math . Floor ( ( i + 1 ) * bucketSize ) + 1 ) ;
338+ bucketEnd = bucketEnd > array . Length ? array . Length : bucketEnd ;
339+
340+ // Point a
341+ float aX = a ;
342+ float aY = array [ a ] ;
343+ float maxArea = - 1 ;
344+ for ( ; bucketStart < bucketEnd ; bucketStart ++ )
345+ {
346+ // Calculate triangle area over three buckets
347+ if ( bucketStart >= array . Length )
348+ {
349+ continue ;
350+ } ;
351+ float area = Math . Abs ( ( aX - avgX ) * ( array [ bucketStart ] - aY ) - ( aX - ( float ) bucketStart ) * ( avgY - aY ) ) * 0.5f ;
352+ if ( area > maxArea )
353+ {
354+ maxArea = area ;
355+ maxAreaPointX = bucketStart ;
356+ maxAreaPointY = array [ bucketStart ] ;
357+ nextA = bucketStart ; // Next a is this b
358+ }
359+ }
360+ // Pick this point from the Bucket
361+ window [ insert ] = maxAreaPointY ;
362+ windowX [ insert ] = maxAreaPointX ;
363+ insert ++ ;
364+
365+ // Current a becomes the next_a (chosen b)
366+ a = nextA ;
367+ }
368+
369+ window [ insert ] = array [ ^ 1 ] ; // Always add last
370+ windowX [ insert ] = array . Length ;
371+
372+ return window ;
373+ }
293374 }
294375}
0 commit comments