-2

When I open large audio files, I get an out of memory error.

I know this method isn't common, so I thought I have to ask a real boffin.

I have the following happening:

public static List<List<float>> int_filenamewavedataRight = new List<List<float>>();

From there I open up an audio file and load the audio level values in this array, so I can view them correctly through the naudio library.

I clear the arrays like so for a new file:

int_filenamewavedataRight.Clear();

int_filenamewavedataRight.Add(new List<float>());

Then, I load all of the values in to memory for speedy display of the waveforms:

waveStream.Position = 0;
int bytesRead; 
byte[] waveData = new byte[bytesPerSample];
waveStream.Position = 0; // startPosition + (e.ClipRectangle.Left * bytesPerSample * samplesPerPixel);

int samples = (int)(waveStream.Length / bytesPerSample);

wavepeakloaded = 0;
int OldPrecentVal = 0;

for (int x = 0; x < samples; x++)
{
     
    short high = 0;

    bytesRead = waveStream.Read(waveData, 0, bytesPerSample);
    if (bytesRead == 0)
        break;


    for (int n = 0; n < bytesRead; n += 2)
    {
        short sample = BitConverter.ToInt16(waveData, n); 
        if (sample > high) high = sample;
    }

    float highPercent2 = (float)Math.Round(((((float)high) - short.MinValue) / ushort.MaxValue), 2);              

    // ERRORING HERE
    // ERRORING HERE

    int_filenamewavedataRight[filename_value].Add((float)Math.Round(highPercent2, 2)); 

    // ERRORING HERE
    // ERRORING HERE

}

Small audio files, of a typical song with 5 mins in length are fine, but longer files, of 25mins or more, create an exception when a count of 67108864 occurs, and I then get an "Exception of type 'System.OutOfMemoryException' was thrown."

x = {"Exception of type 'System.OutOfMemoryException' was thrown."} 

ex.StackTrace "   at System.Collections.Generic.List`1.set_Capacity(Int32 value)\r\n   at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)\r\n   at System.Collections.Generic.List`1.Add(T item)\r\n   at APP.WaveViewer.LoadWaveToMemory(Int32 filename_value) in  WaveViewer.cs:line 1391"

I'm using a list of a list so that I can address the audio files like a simple array, but as I don't know the initial size of the array, I can specify a size initially.

I'm also pre-loading the waveform data like this so I can have playback, zoom and pan the audio file at the same time.

Is this easily fixable, or should I find a different way of doing this, such as writing these peak volume values to a temporary file, rather than keeping them in memory, or is there a better way?

I've looked this up in various places on the net, such as here however, it seems like a rare thing to be doing this.

Thanks.

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
vr_driver
  • 1,867
  • 28
  • 39
  • 1
    If you have an array that large it is reasonable to use that flag. `Int32` is a fairly arbitrary limit from a conceptual standpoint. – Aluan Haddad Sep 04 '20 at 14:30
  • I think that this datastructure : public static List> int_filenamewavedataRight = new List>(); is problematic. Consider this: Span and Memory. I would also consider using Garbage collection API to free resources at the right time. You can also use multi-threading to manage the task.. before memory reaches max, let the thread wait, and then continue. Use Diagnostic classes to achieve so and debug in general. – Dan Friedman Sep 04 '20 at 14:31
  • 2
    are you sure you are not running your process in 32bit mode? – JonasH Sep 04 '20 at 14:48
  • 1
    @JonasH There's a still a default 2GB limit for a single object even in 64bit builds, as someone noted in the question linked by OP. – itsme86 Sep 04 '20 at 14:52
  • @itsme86, I know, but 67108864 floats should be fairly far from the 2Gb limit. If he is running 32 bit problems would occur much sooner, some versions of VS default to 32 bit, and it should be very easy to check. – JonasH Sep 04 '20 at 14:58
  • I'm pretty sure it's 32bit. I'll confirm in the morning. It's 1am here in Australia. – vr_driver Sep 04 '20 at 15:01
  • @itsme86 list of something is not a single object, it's a collection of single objects, thus 2GB object size limit is not applicable here. Yes, collection itself is an object and consumes memory but size of included in the list objects is not counted in the list's size as object. – aepot Sep 04 '20 at 19:52
  • Confirmed to be x86. I have now tried compiling on x64 and surprisingly, it doesn't have this problem. – vr_driver Sep 05 '20 at 03:14
  • Thank you all. After researching more, I will be using x64 bit from now on, and imposing a limit on a potential 32bit version. Maybe I'm just old school, and hadn't thought that 99.99% of people are using x64. cheers. :) – vr_driver Sep 06 '20 at 09:13

1 Answers1

0

The simple answer is it was running in 32bit (x86) which doesn't have enough allocation for 50,000,000+ samples.

Instead, changing the program to x64 has solved that specific problem.

That's what I like about SO where you can pool resources from so many people and learn as you ask questions.

vr_driver
  • 1,867
  • 28
  • 39
  • Do you really need to keep all of those samples in-memory though? Audio-processing software has been able to process raw wave-form data larger than physical memory for decades by being smart about what's kept in-memory. – Dai Sep 08 '20 at 01:59
  • Yes, I completely agree, so hopefully not too far in the future though. I have just found a library that will draw things with incredible speed, making my original efforts redundant. I'll just have to rewrite some things now and work of optimising it further and trying different methods I haven't done or thought of before. – vr_driver Sep 08 '20 at 07:13