This article mainly introduces how to use Python to create a simple piano program, and how to use a keyboard to play the program, including variable speed and variable adjustment functions. For more information, see the next audio clip, change its pitch 50 times and match each new audio to a key on the keyboard. then you can turn your computer into a piano!
A piece of audio can be encoded as an array (or a list) of values, such:
We can remove the value of one second every second in the array to speed the audio twice.
In this way, we not only halved the length of the audio, but also doubled its frequency so that it had a higher pitch than the original one ).
On the contrary, if we repeat each value in the array, we will get a slower, longer cycle, that is, the audio with a lower pitch:
Here is a simple Python function that can change the audio speed by any factor:
Import numpy as np def speedx (sound_array, factor): "multiply the audio speed by any factor" indices = np. round (np. arange (0, len (snd_array), factor) indices = indices [indices <len (snd_array)]. astype (int) return sound_array [indices. astype (int)]
This problem is more difficult because it changes the length of the audio while maintaining its pitch (variable speed, sound stretching )), or keep the length of the audio while changing the pitch )).
Variable speed
Variable speed can be achieved through the traditional phase audio (phase vocoder, interested friends can read the Wikipedia page. First, the audio is divided into overlapping bits, and then these bits are re-arranged so that they overlap more (will shorten the sound length) or less (will stretch the audio length ), as shown in:
The difficulty is that the rearranged bits may have a serious mutual influence, so here we need to use the phase transformation to ensure that there is no impact between them. Here is a piece of Python code, which is taken from this webpage (you can understand it if it cannot be opened. -- Translator's note ):
Def stretch (sound_array, f, window_size, h): "stretch the audio by factor 'F'" phase = np. zeros (window_size) hanning_window = np. hanning (window_size) result = np. zeros (len (sound_array)/f + window_size) for I in np. arange (0, len (sound_array)-(window_size + h), h * f): # two subsequences that may overlap with each other a1 = sound_array [I: I + window_size] a2 = sound_array [I + h: I + window_size + h] # Re-synchronize the second sequence s1 = np according to the first sequence. fft. fft (hanning_window * a1) s2 = np. fft. fft (hanning_window * a2) phase = (phase + np. angle (s2/s1) % 2 * np. pi a2_rephased = np. fft. ifft (np. abs (s2) * np. exp (1j * phase) # add to the result i2 = int (I/f) result [i2: i2 + window_size] + = hanning_window * a2_rephased result = (2 ** (16-4) * result/result. max () # normalization (16 bit) return result. astype ('int16 ')
Adjustment
Once you implement the variable speed, it is not difficult to adjust the variable. If you need a higher pitch, you can first stretch the audio and keep the pitch unchanged, and then speed up the audio so that the final audio will have the same length as the original audio, a higher frequency means a higher pitch.
Doubling the frequency of a piece of audio will increase the pitch by an octal, that is, 12 half tones. Therefore, to increase the pitch to n half tones, we need to multiply the frequency by a factor of 2 ^ (n/12 ):
Def pitchshift (snd_array, n, window_size = 2 ** 13, h = 2 ** 11 ): "increase the pitch of an audio clip by ''n'' half tone" factor = 2 ** (1.0 * n/12.0) stretched = stretch (snd_array, 1.0/factor, window_size, h) return speedx (stretched [window_size:], factor)
Mini Program: computer piano
Let's take a look at our changes. Let's tap into the bowl to determine a "standard pitch ":
[Youku id = "XNzM1NDM2NTky"]
Next we will create 50 pitch changes based on the previous audio, from very low to very high:
from scipy.io import wavfile fps, bowl_sound = wavfile.read("bowl.wav")tones = range(-25,25)transposed = [pitchshift(bowl_sound, n) for n in tones]
Next, in the order in this file, we will match each audio to a key position on the keyboard, as shown in:
We only need to tell the computer in the code to play the corresponding sound when a key is pressed, and then stop playing after the key is released:
Import pygame. mixer. init (fps,-16, 1,512) # Too flexible screen = pygame. display. set_mode (640,480) # set focus # get the list of keyboard key locations in the correct sequence # ''keys ''such as ['Q', 'W', 'e ', 'R'...] sort keys = open ('typewriter. kb '). read (). split ('\ n') sounds = map (pygame. sndarray. make_sound, transposed) key_sound = dict (zip (keys, sounds) is_playing = {k: False for k in keys} while True: event = pygame. event. wait () if event. type in (pygame. KEYDOWN, pygame. KEYUP): key = pygame. key. name (event. key) if event. type = pygame. KEYDOWN: if (key in key_sound.keys () and (not is_playing [key]): key_sound [key]. play (fade_ms = 50) is_playing [key] = True elif event. key = pygame. k_ESCAPE: pygame. quit () raise KeyboardInterrupt elif event. type = pygame. KEYUP and key in key_sound.keys (): key_sound [key]. fadeout (50) # stop playing and fade out is_playing [key] = False in 50 ms
In this way, we turn the computer into a piano! So far, let me show you a Turkish march to express my gratitude for your patience in reading this article:
[Youku id = "XNzM1NDQ1MDA4"]
If you want to try it on your own, you can download all the files you need here. Because not everyone uses Python, I also use Javascript/HTML5 (here) to implement a computer piano, but it is not particularly ideal. It would be great to have experienced HTML5, JS, and elm programmers to improve or rewrite them from scratch.
What to do next?
More often, I find that computers are rarely used to perform performances. I understand that using a piano keyboard or recording directly from an instrument is much easier, but take a look at what you can do with just one bowl and 60 lines of Python code!
Even a very cheap computer has so many controls to implement a sloppy music station: you can sing to the microphone, make gestures to the camera, and draw with the mouse, then use the keyboard to complete the remaining things. There are so many ways to express yourself, and each method has a Python package ...... Are there any talented talents?