[Python] Termin avec interface souris

Contexte

J'adore les trackballs de Kensington. Lorsqu'on lui a demandé «Est-ce facile d'utiliser une boule de commande?», J'ai parfois répondu: «C'est facile de s'y habituer, mais ça ressemble à Termin». Est-ce vraiment Termin? !! Afin de vérifier cela, j'ai créé un programme qui change la hauteur et le volume en fonction de la position de la souris.

Cadre environnemental

Utilisez les 5 modules suivants.

import pyaudio
import numpy as np
import pyautogui
import keyboard 
from scipy import arange, cumsum, sin, linspace
from scipy import pi as mpi

Cette fois, pyautogui est utilisé pour obtenir les informations de position de la souris. Si la version pip est 20.2.1, il semble qu'une erreur d'installation se produira (à partir du 2020.8.11). J'ai rétrogradé la pymsgbox qui était installée avec et l'ai installée manuellement pour l'éviter. À propos, la sous-machine était la version précédente de pip lui-même, mais dans ce cas, j'ai pu l'installer sans générer d'erreur. (Article précédent https://qiita.com/Lemon2Lemonade/items/0a24a4b65c9031536f6e)

pyaudio est un module qui produit des sons avec python, et le clavier obtient les valeurs d'entrée du clavier.

Valeur d'entrée

RATE est la soi-disant fréquence d'échantillonnage, et cette fois je l'ai réglée à 44,1 kHz, ce qui est identique à CD. minfreq est la fréquence la plus basse. C'est C, qui est une octave plus bas que la A à 442Hz et monte un court 3 degrés (en loi moyenne, multiplier la fréquence par la 12ème racine de 2 élève une demi-note). La plage de tonalité est la plage de lecture de Termin. Dans le texte, la fréquence est multipliée par une constante telle que minfreq * tonerange, donc doubler signifie une octave. période est la durée du son. Détecte la position du curseur toutes les 0,01 secondes. minamp est le volume minimum et amprange est la plage de volume.

RATE = 44100 #Fréquence d'échantillonnage
CHUNK = 1024 #tampon
PITCH = 442 #pas
minfreq = PITCH/2*2**(3/12)
tonerange = 2
period = 0.01
minamp = 0.1
amprange = 0.5

Détection de position

Tout d'abord, obtenez la taille de la fenêtre.

def get_window_size():
    window_size = pyautogui.size()
    return window_size

Réglez la hauteur à changer lorsque le curseur est déplacé verticalement et le volume à changer lorsque le curseur est déplacé horizontalement. Calculez la position relative de l'écran. La hauteur est la note la plus basse en bas de l'écran et la note la plus élevée en haut de l'écran. D'autre part, le volume doit être minimum au centre de l'écran et maximum aux deux extrémités. Obtient la position relative du curseur sur l'axe x (direction horizontale) ou l'axe y (direction verticale).

def distance():
    window_size = get_window_size()
    x, y = pyautogui.position()
    x_dist = np.sqrt((x-window_size.width/2)**2)
    y_dist = abs(y-window_size.height)
    x_max = np.sqrt((window_size.width/2)**2)
    y_max = window_size.height
    x_ratio = x_dist/x_max 
    y_ratio = y_dist/y_max
    return x_ratio, y_ratio

Correspond à la position de l'écran avec la hauteur et le volume.

def tonemapping():
    ratio = distance()
    freq = minfreq*2**(tonerange*ratio[1])
    return freq

def ampmapping():
    ratio = distance()
    amp = minamp+amprange*ratio[0]
    return amp

Réglage et lecture des ondes sinusoïdales (source sonore)

A part ça, j'ai eu du mal ici. Si vous ne jouez qu'un certain son pendant une certaine période de temps par rapport à la position, le son sera haché et du bruit sera ajouté. Par conséquent, mémorisez les conditions avant la boucle (fréquence de hauteur et d'onde sinusoïdale, phase, amplitude) afin qu'elles puissent être connectées en douceur.

Je l'ai fait en référence au site suivant. http://yukara-13.hatenablog.com/entry/2013/12/23/053957

Si vous ne correspondez pas à la phase (si vous ne faites pas d'onde de péché connectée), vous obtiendrez un «bourdonnement». Si vous calculez la période de lecture en 0,01 seconde, le bruit sera plus perceptible que l'onde sinueuse.

def make_time_varying_sine(start_freq, end_freq, start_A, end_A, fs, sec, phaze_start):
    freqs = linspace(start_freq, end_freq, num = int(round(fs * sec)))
    A = linspace(start_A, end_A, num = int(round(fs * sec)))
    phazes_diff = 2. * mpi * freqs / fs    #Quantité de changement de fréquence angulaire
    phazes = cumsum(phazes_diff) + phaze_start    #phase
    phaze_last = phazes[-1]
    ret = A * sin(phazes) #Synthèse sinusoïdale
    return ret, phaze_last

def play_wave(stream, samples):
    stream.write(samples.astype(np.float32).tostring())

def play_audio():
    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paFloat32,
                    channels=1,
                    rate=RATE,
                    frames_per_buffer=CHUNK,
                    output=True)
    freq_old = minfreq
    amp_old = minamp
    phaze = 0
    
    while True:
        try:
            if keyboard.is_pressed('q'):
                stream.close()
                break  # finishing the loop
            else:
                freq_new = tonemapping()
                amp_new = ampmapping()
                tone = make_time_varying_sine(freq_old, freq_new, amp_old, amp_new, RATE, period, phaze)
                play_wave(stream, tone[0])
                freq_old = freq_new
                amp_old = amp_new
                phaze = tone[1]
        except:
            continue
            
if __name__ == '__main__':
    play_audio()

Recommended Posts

[Python] Termin avec interface souris
Statistiques avec python
[Automation] Manipulez la souris et le clavier avec Python
Python avec Go
Twilio avec Python
Intégrer avec Python
Jouez avec 2016-Python
AES256 avec python
Testé avec Python
python commence par ()
avec syntaxe (Python)
Bingo avec python
Zundokokiyoshi avec python
Excel avec Python
Micro-ordinateur avec Python
Cast avec python
[Python] Dessinez un Mickey Mouse avec une tortue [Débutant]
Zip, décompressez avec python
Django 1.11 a démarré avec Python3.6
Jugement des nombres premiers avec Python
Python avec eclipse + PyDev.
Grattage en Python (préparation)
Essayez de gratter avec Python.
Apprendre Python avec ChemTHEATER 03
Recherche séquentielle avec Python
"Orienté objet" appris avec python
Exécutez Python avec VBA
Manipuler yaml avec python
Communication série avec python
Apprendre Python avec ChemTHEATER 05-1
Apprenez Python avec ChemTHEATER
Exécutez prepDE.py avec python3
1.1 Premiers pas avec Python
Collecter des tweets avec Python
Binarisation avec OpenCV / Python
3. 3. Programmation IA avec Python
Méthode Kernel avec Python
Non bloquant avec Python + uWSGI
Grattage avec Python + PhantomJS
Publier des tweets avec python
Conduisez WebDriver avec python
Utiliser mecab avec Python 3
[Python] Redirection avec CGIHTTPServer
Analyse vocale par python
Pensez à yaml avec python
Utiliser Kinesis avec Python
Premiers pas avec Python
Utiliser DynamoDB avec Python
Getter Zundko avec python
Gérez Excel avec python
Loi d'Ohm avec Python
Jugement des nombres premiers avec python
Exécutez Blender avec python
Résoudre des maths avec Python
Python à partir de Windows 7
Carte thermique par Python + matplotlib
Multi-processus de manière asynchrone avec python
Programmation Python avec Atom
Apprendre Python avec ChemTHEATER 02
Utilisez Python 3.8 avec Anaconda
Programmation compétitive avec python