KinMaynard / soundscope

Audio Imager & Editor Python Package
MIT License
0 stars 0 forks source link

Performance Speed Up #24

Open KinMaynard opened 3 years ago

KinMaynard commented 3 years ago

Blitting plotting, drawing, zoom, pan & buttons to speed up performance of especially visualizer function.

KinMaynard commented 3 years ago

New theory that speed issues are from the size of the data. It's probably calling a lot of draw for each data point and audio usually has around 44100 per second points. So chunking or using collections would help and might fix the problem.

KinMaynard commented 3 years ago

Collections marginally helps but what needs to be done is chunking the data. I want to use a block-wise generator instead of an array of all the data for the display portions of this code. Since display doesn't require as much fidelity as playback I want to use a much smaller buffer size for the audio data. Displaying 44100 data points per second is unnecessary and impossible. It would be far more prudent to display a small power of 2 say 1024. I can use this small buffer for the display portions and use the full fidelity of the audio for playback/dsp. This error came from only understanding how necessary high fidelity is for playback and not realizing that it isn't necessary for visualization and in fact causes severe performance issues.

So where do I want to use blocks and where arrays? Use blocks for visualization functions & their tests and use arrays for dsp.

KinMaynard commented 3 years ago

Adding block argument to visualization functions:

KinMaynard commented 3 years ago

Accidental closing of issue. Reopened.

KinMaynard commented 3 years ago

What do I want to accomplish using block processing instead of an array at 441khz/Sec?

I want to downsample the data to visualize it at around 1024 samples/sec. So I will run a generator making blocks of that size and plot 1 block per second. It's not enough to set the blocksize I also need the sample rate to be the blocksize as well and I also can process this into an array inside the import function and not change my current function calls.

KinMaynard commented 3 years ago

I don't even need blocks until I want realtime so I can just return a downsampled array at import along with the full fidelity one.

KinMaynard commented 3 years ago

Turns out you cannot downsample with soundfile.read since it reads the sample rate from the file unless it's raw input.

KinMaynard commented 3 years ago

Let's perform the downsampling ourselves inside the import function and return 2 arrays as previous.

KinMaynard commented 3 years ago

Downsample methods: Resample - Take every nth sample Bin - Average of Bins Interpolate - Fit curve

KinMaynard commented 3 years ago

Preserving docstring for buffersize for later use buffer: buffer size for block generator [32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384] or default None

KinMaynard commented 3 years ago

So I would like to use both bins and interpolation to downsample the array for the analysis functions. I'll make a button for this in the magnitude spectrum plot at least possibly one in the spectrogram too.

KinMaynard commented 3 years ago

Now the question is what kind of padding do I want to use for the last bin in case the length of the array isn't divisible by the bin size.

numpy padding options:

‘constant’ (default) Pads with a constant value. ‘edge’ Pads with the edge values of array. ‘linear_ramp’ Pads with the linear ramp between end_value and the array edge value. ‘maximum’ Pads with the maximum value of all or part of the vector along each axis. ‘mean’ Pads with the mean value of all or part of the vector along each axis. ‘median’ Pads with the median value of all or part of the vector along each axis. ‘minimum’ Pads with the minimum value of all or part of the vector along each axis. ‘reflect’ Pads with the reflection of the vector mirrored on the first and last values of the vector along each axis. ‘symmetric’ Pads with the reflection of the vector mirrored along the edge of the array. ‘wrap’ Pads with the wrap of the vector along the axis. The first values are used to pad the end and the end values are used to pad the beginning. ‘empty’ Pads with undefined values.

Also I think I just want to pad the last bin if possible. It seems numpy pad pads both start and end of the array.

KinMaynard commented 3 years ago

Lengths of test arrays:

silence44100-infdBFS_Mono.aiff 441000

white88k-3dBFS.wav 2646001

hdchirp88k-3dBFS_lin.wav 44101

sin_44100100Hz-3dBFS_1s.wav 44101

hdsweep_1Hz44000Hz-3dBFS_30s.wav 2646001

silence44100-infdBFS_Stereo.aiff 441000

whitenoise_44100_0dBFS_Stereo.aiff 441000

hdchirp88k-3dBFS_lin_Stereo.aiff 44101

sin_44100440Hz-.8dBFS_Stereo.aiff 441000

Saija Original Mix.aiff 18050535

KinMaynard commented 3 years ago

Turns out downsampling into bins does not significantly improve performance even when at very low fidelity (high bin sizes). The next step will be to try linear interpolation. If this fails then I will need to attempt blitting again probably alongside some kind of downsampling.

KinMaynard commented 3 years ago

So I am not sure if linear interpolation will speed up the program too much since even heavily downsampled arrays still have performance issues. I believe the next step to be attempting blitting once more and trying to use the matplotlib doc methods for performance.

KinMaynard commented 3 years ago

backend code for blitting:

# use backend that supports animation & blitting
mpl.use('Qt5Agg')