diff options
| author | Brianna Rainey | 2026-01-28 17:49:58 -0500 |
|---|---|---|
| committer | GitHub | 2026-01-28 17:49:58 -0500 |
| commit | f66eb99465c61232a7f649e66bee59504bb0e52c (patch) | |
| tree | 40d4f2e4e7cea033e4a68da025c7d91295e71cfb /src/avp/toolkit/visualizer.py | |
| parent | 864898419e810055b51e3a32fccb00a62aab9a6b (diff) | |
v2.2.1 - fix #74, fix #92, add optional 64th bar to Classic Visualizer, improve Conway default (#93)
* update gitignore
ignore profiling and coverage data
* F1 opens help window, create appName variable, move undostack class
* fix kaleidoscope effect, increase default Y values by +4
the increased y values allow the cells to continue animating for more than 60 minutes instead of 30 (at default 60f/t)
* update version number
* add minimumWidth to undo history window
* Classic Visualizer: option to include 64th bar
* Waveform component: fix #74 - new animation speed option
* move shared visualizer code into toolkit
* Waveform component: compress audio by default
* Waveform component: fix 100% animation speed
* new components receive random color
* update to Qt 6
* fix pushbutton stylesheet
* fix #92: replace ok/cancel with save/discard/cancel
* remove obsolete PaintColor subclass
* mv common shadow code into addShadow func
* add 3rd option of ok/cancel back to showMessage
the 3 options are:
- ok
- ok/cancel
- save/discard/cancel
* Image component: add shadow option
* small test of rgbFromString
* fix color tuple string
* test another way to get comp names from CLI
* rename component tests, add some more
* Image component: scale shadow based on resolution
* catch AttributeError if previewRender returns None
* Text component: fix blur radius only able to increase
the relativeWidgets system causes QDoubleSpinbox to only allow increases, because it really only works with integeres, so I changed the blur radius into a normal QSpinBox. I noted where the problem exists within component.py for future reference. This commit also removes an unneeded VerticalLayout from the ui file
* remove unnecessary QVBoxLayout
* paste shadow at x,y instead of using offset method
* fix tests due to shadow change
* don't print warning in connectWidget due to QFontComboBox
Diffstat (limited to 'src/avp/toolkit/visualizer.py')
| -rw-r--r-- | src/avp/toolkit/visualizer.py | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/avp/toolkit/visualizer.py b/src/avp/toolkit/visualizer.py new file mode 100644 index 0000000..c55a3f3 --- /dev/null +++ b/src/avp/toolkit/visualizer.py @@ -0,0 +1,87 @@ +"""Functions used to transform and manipulate audio for use by visualizers""" + +from copy import copy +import numpy + + +def createSpectrumArray( + component, + completeAudioArray, + sampleSize, + smoothConstantDown, + smoothConstantUp, + scale, + progressBarUpdate, + progressBarSetText, +): + lastSpectrum = None + spectrumArray = {} + for i in range(0, len(completeAudioArray), sampleSize): + if component.canceled: + break + lastSpectrum = transformData( + i, + completeAudioArray, + sampleSize, + smoothConstantDown, + smoothConstantUp, + lastSpectrum, + scale, + ) + spectrumArray[i] = copy(lastSpectrum) + + progress = int(100 * (i / len(completeAudioArray))) + if progress >= 100: + progress = 100 + progressText = f"Analyzing audio: {str(progress)}%" + progressBarSetText.emit(progressText) + progressBarUpdate.emit(int(progress)) + return spectrumArray + + +def transformData( + i, + completeAudioArray, + sampleSize, + smoothConstantDown, + smoothConstantUp, + lastSpectrum, + scale, +): + if len(completeAudioArray) < (i + sampleSize): + sampleSize = len(completeAudioArray) - i + + window = numpy.hanning(sampleSize) + data = completeAudioArray[i : i + sampleSize][::1] * window + paddedSampleSize = 2048 + paddedData = numpy.pad(data, (0, paddedSampleSize - sampleSize), "constant") + spectrum = numpy.fft.fft(paddedData) + sample_rate = 44100 + frequencies = numpy.fft.fftfreq(len(spectrum), 1.0 / sample_rate) + + y = abs(spectrum[0 : int(paddedSampleSize / 2) - 1]) + + # filter the noise away + # y[y<80] = 0 + + with numpy.errstate(divide="ignore"): + y = scale * numpy.log10(y) + + y[numpy.isinf(y)] = 0 + + if lastSpectrum is not None: + lastSpectrum[y < lastSpectrum] = y[ + y < lastSpectrum + ] * smoothConstantDown + lastSpectrum[y < lastSpectrum] * ( + 1 - smoothConstantDown + ) + + lastSpectrum[y >= lastSpectrum] = y[ + y >= lastSpectrum + ] * smoothConstantUp + lastSpectrum[y >= lastSpectrum] * (1 - smoothConstantUp) + else: + lastSpectrum = y + + x = frequencies[0 : int(paddedSampleSize / 2) - 1] + + return lastSpectrum |
