Hampir setiap hari saya mendengarkan musik di smartphone saya dan menggunakan tombol kontrol pada headset. Tapi saya selalu tidak suka satu hal. Saya pulang, terus mendengarkan, headset terhubung ke PC di rumah saya - dan tiba-tiba tombol berhenti bekerja.
Tentu saja, saya mencari solusi untuk masalah ini. Sayangnya, pada Windows fitur luar biasa ini tidak terlalu didukung. Beberapa menit pencarian hanya memberikan sebutan berlumpur di Stack Overflow tentang kartu suara dan pesan dari beberapa orang bahwa semuanya bekerja dengan baik di laptop mereka.
Ini tidak membuat saya takut - dan saya memutuskan untuk menerima masalah sebagai tantangan yang menarik: apakah mungkin membuat semacam program untuk mengaktifkan tombol kontrol, jika sama sekali tidak ada dukungan perangkat keras untuk mereka? Jawabannya adalah ya, Anda bisa. Dan inilah cara melakukannya dalam waktu setengah jam.
Cara Kerja Tombol Headset Android
Hal pertama yang harus dipahami adalah cara kerja tombol headset. Pencarian cepat di Internet menemukan
spesifikasi ini dari dokumentasi Android. Ada bagan di sana.

Seperti yang dapat Anda pahami, ketika Anda menekan tombol pada headset, sirkuit pada salah satu resistor ditutup. Yang perlu diperhatikan adalah Tombol A (Play / Pause / Hook) dengan hambatan 0 ohm, yaitu, korsleting mikrofon. Jika kami dapat mendeteksi korsleting di mikrofon, maka kami dapat menentukan penekanan tombol Play / Pause.
Tes hipotesis
Sebelum memulai pemrograman, saya ingin memeriksa kewajaran alasan kami pada prinsipnya. Artinya, fakta bahwa sinyal dari mikrofon dapat ditentukan dengan menekan tombol Play / Pause. Untungnya, untuk ini cukup dengan hanya merekam suara di komputer dan melihat hasilnya. Saya meluncurkan Audacity, menekan tombol Mainkan / Jeda selama perekaman - dan menerima sinyal seperti itu.
BingoSeperti yang Anda lihat, menekan tombol jelas tercermin dalam bentuk gelombang: penurunan tiba-tiba ke followed1 diikuti oleh transisi tiba-tiba ke 1 dan penurunan bertahap ke 0. Secara spesifik dengan spesifikasi, saya akan berasumsi bahwa sinyal melompat ke 1 dan tetap di sana sampai tombol dilepaskan, tetapi pada kenyataannya itu terlihat berbeda. Meskipun demikian, gambar seperti itu masih mudah dideteksi jika Anda menangkap aliran audio dari mikrofon.
Pengambilan suara dengan Python
Mengetahui cara mendeteksi penekanan tombol pada headset, Anda dapat memikirkan tujuan utama: cara mengontrol pemutar di desktop menggunakan tombol headset.
Langkah pertama adalah mendeteksi klik tombol. Untuk melakukan ini, Anda perlu mengambil aliran audio dari mikrofon dan menemukan tanda tangan berbeda yang kita lihat sebelumnya. Untuk mempermudah, kami mengimplementasikan solusi dengan Python. Setelah pencarian kecil lainnya di Internet, saya menemukan paket bernama sounddevice, yang memungkinkan Anda untuk mengambil abstrak dari bagian yang paling sulit - pengambilan audio nyata dari mikrofon.
Sedikit pengkodean memberi kita yang berikut:
import sounddevice as sd SAMPLE_RATE = 1000
Kode semacam itu terus-menerus menghasilkan nilai rata-rata dari setiap kumpulan sampel. Kami menetapkan laju pengambilan sampel menjadi 1000, yang sangat kecil untuk pemrosesan suara (44100 biasanya digunakan), tetapi kami benar-benar tidak membutuhkan banyak akurasi. Ukuran blok menentukan berapa banyak sampel dalam buffer memicu panggilan balik. Sekali lagi, kami menetapkan nilai yang sangat rendah. Ukuran blok 100 dan laju sampling 1000 sebenarnya berarti memicu 10 kali per detik, di mana hanya 100 sampel diproses dengan setiap panggilan.
Deteksi klik tombol: mungkin terlalu mudah
Sekarang kami menangkap aliran audio dan kami dapat menerapkan mekanisme nyata untuk mendeteksi penekanan tombol. Ingat bahwa sinyal melonjak ke 1 setiap kali Anda menekan. Ini menyarankan cara termudah untuk mendeteksi: jika
N blok berturut-turut memiliki nilai sinyal di atas 0,9, yaitu, klik.
Kami menerapkan algoritma dalam fungsi kami:
import sounddevice as sd SAMPLE_RATE = 1000
Faktanya, kami meluncurkan penghitung internal, berapa banyak blok yang diproses memenuhi persyaratan ambang batas, yang hanya diatur ke 0,9, memberikan kebisingan sampel yang tak terhindarkan. Jika blok tidak memenuhi persyaratan, penghitung diatur ulang - dan kami mulai lagi.
is_held
variabel
is_held
terpicu agar tidak mendaftarkannya berulang kali jika tombol tidak dilepaskan.
Kontrol pemutaran Windows
Sekarang tinggal mengganti komentar
"Tombol itu ditekan!" Dalam kode nyata untuk mengontrol pemutaran audio di Windows. Google lagi untuk mencari tahu bagaimana melakukan ini: ternyata Anda dapat mengontrol pemutaran dengan mensimulasikan penekanan tombol dengan
kode kunci virtual yang sesuai.
Ternyata simulasi penekanan tombol sangat mudah dengan paket
pywin32 , yang hanya shell Python untuk Windows API. Menyatukan semuanya, kita dapat membuat fungsi berikut:
import win32api import win32con VK_MEDIA_PLAY_PAUSE = 0xB3 def toggle_play(): win32api.keybd_event(VK_MEDIA_PLAY_PAUSE, 0, 0, 0)
Dan kami berhasil!
toggle_play
fungsi
toggle_play
di tempat kode di mana komentar
"Tombol ditekan!" , memungkinkan Anda untuk mengontrol pemutar media di Windows menggunakan tombol pada headset Android.
Pengujian telah menunjukkan bahwa kodenya bekerja dengan sangat baik. Satu-satunya perbedaan antara fungsi pada Android dan Windows adalah sedikit keterlambatan saat Anda menekan tombol, tetapi Anda dapat hidup dengannya.
Jadi apa yang terjadiSkrip Python terdiri dari 51 baris yang mengaktifkan tombol-tombol pada headset Android pada Windows. Kode sumber terakhir untuk proyek ini ada
di Github .
Tunggu, itu belum semuanya!
Setelah menggunakan program ini dengan senang hati selama beberapa jam, saya melihat ada masalah serius:

Program ini menggunakan hampir 30% CPU! Jelas, ini tidak dapat diterima selama kerja yang panjang, sesuatu perlu dilakukan. Melihat kode tersebut, saya menyadari bahwa utas utama berada dalam status siaga di loop utama, meskipun tidak ada yang terjadi di sana. Solusi paling logis adalah dengan hanya menidurkan utas selamanya: karena panggilan balik dipanggil secara otomatis, kita masih tidak memerlukan perulangan.
from time import sleep if __name__ == '__main__': controller = HeadsetButtonController() while True: sleep(10)

Saya juga tidak ingin menjalankan skrip Python secara manual setelah setiap startup komputer. Untungnya, Python untuk Windows hadir dengan utilitas bermanfaat bernama pythonw.exe yang memulai proses daemon tanpa terminal tersambung. Kami menempatkan pintasan untuk proses ini di
direktori Microsoft \ Windows \ Start Menu \ Programs \ Startup , menentukan skrip kami sebagai argumen pertama - maka aplikasi secara otomatis memulai dan berjalan dengan tenang di latar belakang.