|
18 | 18 | # along with Friture. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
|
20 | 20 | from PyQt5.QtCore import QObject |
21 | | -from numpy import log10, argmax, zeros, arange, floor, float64 |
| 21 | +from numpy import log10, argmax, zeros, arange, floor, float64, ones |
22 | 22 | from friture.audioproc import audioproc # audio processing class |
23 | 23 | from friture.spectrum_settings import (Spectrum_Settings_Dialog, # settings dialog |
24 | 24 | DEFAULT_FFT_SIZE, |
@@ -105,11 +105,21 @@ def harmonic_product_spectrum(self, sp): |
105 | 105 | # for pitch detection are good. |
106 | 106 | product_count = 3 |
107 | 107 |
|
108 | | - # Downsample and multiply |
109 | 108 | harmonic_length = sp.shape[0] // product_count |
110 | | - res = sp[:harmonic_length].copy() |
111 | | - for i in range(2, product_count + 1): |
112 | | - res *= sp[::i][:harmonic_length] |
| 109 | + |
| 110 | + # common case: product_count == 3 — multiply the three slices |
| 111 | + # directly. This avoids allocating a temporary ones array and still |
| 112 | + # doesn't make copies of the original `sp` beyond NumPy's routine |
| 113 | + # temporary results for the elementwise multiplication. |
| 114 | + if product_count == 3: |
| 115 | + # Downsample and multiply |
| 116 | + res = (sp[:harmonic_length] |
| 117 | + * sp[::2][:harmonic_length] |
| 118 | + * sp[::3][:harmonic_length]) |
| 119 | + else: |
| 120 | + res = ones(harmonic_length, dtype=sp.dtype) |
| 121 | + for i in range(1, product_count + 1): |
| 122 | + res *= sp[::i][:harmonic_length] |
113 | 123 | return res |
114 | 124 |
|
115 | 125 | def handle_new_data(self, floatdata): |
|
0 commit comments