|
1 | | -# overtonic.py |
| 1 | +# overtonic.py (v1.0.0) |
2 | 2 | # Using Fast Fourier Transforms (FFTs) to determine an instrument based on the musical overtones of its sound |
3 | 3 |
|
4 | 4 | import numpy as np |
|
16 | 16 | # If you change this, remember to change the savefig location to match your directory tree! |
17 | 17 | soundfile = 'sound/sine-a4.wav' |
18 | 18 |
|
| 19 | +soundfilename = soundfile.split('/')[1] # Don't touch |
| 20 | + |
19 | 21 | # Set to True if you want the output figure (with peaks) to save! |
20 | 22 | # Usually best to leave at false except for demos, etc. |
21 | 23 | # Split is a bit questionable, figure out how to do it the right way |
22 | 24 | # This will need to be changed if a different directory tree is used |
23 | 25 | savefig = False |
24 | | -savefigloc = 'images/' + soundfile.split('/')[1] + '.png' |
| 26 | +savefigloc = 'images/' + soundfilename + '.png' |
25 | 27 |
|
| 28 | +# Set to True if you want the output figure (with peaks) to be displayed |
| 29 | +# in a matplotlib window! |
| 30 | +showfig = True |
26 | 31 |
|
27 | 32 | ################################################## |
28 | 33 |
|
|
48 | 53 |
|
49 | 54 | y2 = y + np.polyval([0.002,-0.08,5], x) |
50 | 55 | base = peakutils.baseline(y2, 2) # remove the baseline for a cleaner reading |
| 56 | +y3 = y2-base |
51 | 57 |
|
52 | 58 | # TODO: Conditional-ize the thres and min_dist per sound if possible |
53 | 59 | indexes = peakutils.indexes(y, thres=0.7, min_dist=100) |
54 | 60 |
|
| 61 | +y4 = y3[indexes] |
| 62 | + |
55 | 63 | print("Indexes", indexes) |
56 | 64 | print("array of Indexes", array[indexes]) |
| 65 | +print("y of Indexes (amplitude for array of indexes)", y4) # amplitude |
57 | 66 |
|
58 | | -peakutils.plot.plot(x, y2-base, indexes) # plot x and y with removed baseline, peaks (indexes) |
59 | | -plt.title('Peaks after Removed Baseline') |
| 67 | +peakutils.plot.plot(x, y3, indexes) # plot x and y with removed baseline, peaks (indexes) |
| 68 | +plt.title('Peaks after Removed Baseline: ' + soundfilename) |
60 | 69 | xlabel('Frequency (Hz)') |
61 | 70 | ylabel('Amplitude (dB) without Baseline') |
62 | 71 |
|
63 | | -# Save figure, use for demo only |
| 72 | +# Save figure, use for demo only (see program variables) |
64 | 73 | if savefig == True: |
65 | 74 | plt.savefig(savefigloc, bbox_inches='tight') |
| 75 | +# Show figure, best to leave on (see program variables) |
| 76 | +if showfig == True: |
| 77 | + plt.show() |
66 | 78 |
|
67 | | -plt.show() |
68 | | - |
69 | | -# TODO: |
70 | | - # Set the conditions for the if/else block |
71 | | - # Add a "more or less" part to ensure that this works with other files of the same sound source |
72 | | - |
| 79 | +# TODO (future) - make this whole if/else thing into a neural network so long conditionals don't need to be a thing |
| 80 | + |
73 | 81 | inst = None |
74 | 82 | if len(indexes) == 1: # Sine waves have one peak |
75 | 83 | inst = 'a SINE WAVE' |
76 | 84 | elif len(indexes) == 2: # Whistles have two peaks |
77 | 85 | inst = 'a WHISTLE' |
78 | | -elif len(indexes) == 5: # Pianos have five peaks, but not really and this should be changed! (TODO) |
| 86 | +elif len(indexes) == 5 and round(y4[0] / y4[1], 2) == 1.24 and round(y4[0] / y4[2], 2) == 1.38 and round(y4[0] / y4[3], 2) == 1.24: # it's sketchy but it works |
79 | 87 | inst = 'a PIANO' |
80 | 88 |
|
81 | 89 | if inst: |
|
0 commit comments