[Python] Termin mit Mausschnittstelle

Hintergrund

Ich liebe Kensingtons Trackballs. Auf die Frage "Ist es einfach, einen Trackball zu benutzen?" Antwortete ich manchmal: "Es ist leicht, sich daran zu gewöhnen, aber es fühlt sich an wie Termin." Ist es wirklich Termin? !! Um dies zu überprüfen, habe ich ein Programm erstellt, das die Tonhöhe und Lautstärke abhängig von der Mausposition ändert.

Umgebungseinstellung

Verwenden Sie die folgenden 5 Module.

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

Dieses Mal wird Pyautogui verwendet, um die Mauspositionsinformationen abzurufen. Wenn die Pip-Version 20.2.1 ist, scheint ein Installationsfehler aufzutreten (Stand 2020.8.11). Ich habe die damit installierte pymsgbox heruntergestuft und manuell installiert, um dies zu vermeiden. Der Subcomputer war übrigens die vorherige Version von pip selbst, aber in diesem Fall konnte ich ihn ohne Fehler installieren. (Vorheriger Artikel https://qiita.com/Lemon2Lemonade/items/0a24a4b65c9031536f6e)

pyaudio ist ein Modul, das mit Python Sounds erzeugt, und die Tastatur erhält Tastatureingabewerte.

Eingegebener Wert

RATE ist die sogenannte Abtastfrequenz, und diesmal habe ich sie auf 44,1 kHz eingestellt, was der CD entspricht. minfreq ist die niedrigste Frequenz. Es ist C, das bei 442 Hz eine Oktave niedriger als A ist und um kurze 3 Grad ansteigt (im Durchschnitt erhöht das Multiplizieren der Frequenz mit der 12. Wurzel von 2 eine halbe Note). Der Tonbereich ist der Wiedergabebereich von Termin. Im Text wird die Frequenz mit einer Konstanten wie minfreq * tonerange multipliziert, also bedeutet Verdoppeln eine Oktave. Periode ist die Dauer des Tons. Erkennt die Position des Cursors alle 0,01 Sekunden. minamp ist das Mindestvolumen und amprange ist der Lautstärkebereich.

RATE = 44100 #Abtastfrequenz
CHUNK = 1024 #Puffer
PITCH = 442 #
minfreq = PITCH/2*2**(3/12)
tonerange = 2
period = 0.01
minamp = 0.1
amprange = 0.5

def get_window_size():
    window_size = pyautogui.size()
    return window_size
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
def tonemapping():
    ratio = distance()
    freq = minfreq*2**(tonerange*ratio[1])
    return freq

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

Positionserkennung Ermitteln Sie zuerst die Fenstergröße. Stellen Sie die Tonhöhe so ein, dass sie sich ändert, wenn der Cursor vertikal bewegt wird, und die Lautstärke, die geändert werden soll, wenn der Cursor horizontal bewegt wird. Berechnen Sie die relative Position des Bildschirms. Die Tonhöhe ist die niedrigste Note am unteren Bildschirmrand und die höchste Note am oberen Bildschirmrand. Andererseits sollte die Lautstärke in der Mitte des Bildschirms minimal und an beiden Enden maximal sein. Ruft die relative Position des Cursors auf der x-Achse (horizontale Richtung) oder der y-Achse (vertikale Richtung) ab. Entspricht der Bildschirmposition der Tonhöhe und Lautstärke. Dies ist der Teil, in dem ich es schwer hatte, die Sin Wave (Schallquelle) einzustellen und zu spielen. Wenn Sie nur einen bestimmten Sound für einen bestimmten Zeitraum in Bezug auf die Position abspielen, wird der Sound zerhackt und es werden Geräusche hinzugefügt. Denken Sie daher an die Bedingungen unmittelbar vor der Schleife (Tonhöhe und Sinuswellenfrequenz, Phase, Amplitude), damit sie reibungslos verbunden werden können.

Ich habe es mit Bezug auf die folgende Seite gemacht. http://yukara-13.hatenablog.com/entry/2013/12/23/053957

Wenn Sie nicht mit der Phase übereinstimmen (wenn Sie keine einzige verbundene Sinuswelle erzeugen), erhalten Sie ein "summendes" Rauschen. Wenn Sie die Wiedergabezeit in 0,01 Sekunden berechnen, ist das Rauschen deutlicher als die Sinuswelle.

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    #Betrag der Änderung der Winkelfrequenz
    phazes = cumsum(phazes_diff) + phaze_start    #Phase
    phaze_last = phazes[-1]
    ret = A * sin(phazes) #Sinuswellensynthese
    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 mit Mausschnittstelle
Statistik mit Python
[Automatisierung] Bearbeiten Sie Maus und Tastatur mit Python
Python mit Go
Twilio mit Python
In Python integrieren
Spielen Sie mit 2016-Python
AES256 mit Python
Getestet mit Python
Python beginnt mit ()
mit Syntax (Python)
Bingo mit Python
Zundokokiyoshi mit Python
Excel mit Python
Mikrocomputer mit Python
Mit Python besetzen
[Python] Zeichne eine Mickey Mouse mit Turtle [Anfänger]
Zip, entpacken mit Python
Django 1.11 wurde mit Python3.6 gestartet
Primzahlbeurteilung mit Python
Python mit Eclipse + PyDev.
Scraping in Python (Vorbereitung)
Versuchen Sie es mit Python.
Python lernen mit ChemTHEATER 03
Sequentielle Suche mit Python
"Objektorientiert" mit Python gelernt
Führen Sie Python mit VBA aus
Umgang mit Yaml mit Python
Serielle Kommunikation mit Python
Python lernen mit ChemTHEATER 05-1
Lerne Python mit ChemTHEATER
Führen Sie prepDE.py mit python3 aus
1.1 Erste Schritte mit Python
Tweets mit Python sammeln
Binarisierung mit OpenCV / Python
3. 3. KI-Programmierung mit Python
Kernel-Methode mit Python
Nicht blockierend mit Python + uWSGI
Scraping mit Python + PhantomJS
Tweets mit Python posten
Fahren Sie WebDriver mit Python
Verwenden Sie Mecab mit Python 3
[Python] Mit CGIHTTPServer umleiten
Sprachanalyse mit Python
Denken Sie an Yaml mit Python
Kinesis mit Python betreiben
Erste Schritte mit Python
Verwenden Sie DynamoDB mit Python
Zundko Getter mit Python
Behandle Excel mit Python
Ohmsches Gesetz mit Python
Primzahlbeurteilung mit Python
Führen Sie Blender mit Python aus
Löse Mathe mit Python
Python ab Windows 7
Heatmap von Python + matplotlib
Asynchron mit Python verarbeiten
Python-Programmierung mit Atom
Python lernen mit ChemTHEATER 02
Verwenden Sie Python 3.8 mit Anaconda
Wettbewerbsfähige Programmierung mit Python