web-dev-qa-db-ja.com

Python固定周波数サウンドを再生するためのライブラリ

家に蚊がいます。これは通常、プログラマーのコミュニティーには関係ありません。しかし、17Khzの音を鳴らしてこれらの厄介な生き物を阻止すると主張するデバイスをいくつか見ました。私のラップトップを使用してこれをしたいと思います。

1つの方法は、単一の固定周波数トーンでMP3を作成することです( これはaudacityで簡単に実行できます )、 pythonライブラリで開く と繰り返し再生します。

2つ目は、コンピューターの内蔵スピーカーを使用してサウンドを再生することです。 QBasicSoundに似たものを探しています。

SOUND 17000, 100

pythonそのためのライブラリはありますか?

35
Adam Matan

PyAudiere は、問題に対する単純なクロスプラットフォームソリューションです。

>>> import audiere
>>> d = audiere.open_device()
>>> t = d.create_tone(17000) # 17 KHz
>>> t.play() # non-blocking call
>>> import time
>>> time.sleep(5)
>>> t.stop()

pyaudiere.orgはなくなりました。 サイト およびPython 2(debian、windows)のバイナリインストーラは、ウェイバックマシンを介して利用できます こちらのソースコードpyaudiere-0.2.tar.gz

両方をサポートするには、Python Linux、Windows、OSXで2と3、 pyaudio module を代わりに使用できます:

#!/usr/bin/env python
"""Play a fixed frequency sound."""
from __future__ import division
import math

from pyaudio import PyAudio # Sudo apt-get install python{,3}-pyaudio

try:
    from itertools import izip
except ImportError: # Python 3
    izip = Zip
    xrange = range

def sine_tone(frequency, duration, volume=1, sample_rate=22050):
    n_samples = int(sample_rate * duration)
    restframes = n_samples % sample_rate

    p = PyAudio()
    stream = p.open(format=p.get_format_from_width(1), # 8bit
                    channels=1, # mono
                    rate=sample_rate,
                    output=True)
    s = lambda t: volume * math.sin(2 * math.pi * frequency * t / sample_rate)
    samples = (int(s(t) * 0x7f + 0x80) for t in xrange(n_samples))
    for buf in izip(*[samples]*sample_rate): # write several samples at a time
        stream.write(bytes(bytearray(buf)))

    # fill remainder of frameset with silence
    stream.write(b'\x80' * restframes)

    stream.stop_stream()
    stream.close()
    p.terminate()

例:

sine_tone(
    # see http://www.phy.mtu.edu/~suits/notefreqs.html
    frequency=440.00, # Hz, waves per second A4
    duration=3.21, # seconds to play sound
    volume=.01, # 0..1 how loud it is
    # see http://en.wikipedia.org/wiki/Bit_rate#Audio
    sample_rate=22050 # number of samples per second
)

これは、(Python 3)バージョンの このAskUbuntu回答 をサポートするように変更されています。

23
jfs

モジュール winsound はPythonに含まれているため、インストールする外部ライブラリはなく、必要な機能を実行します(それ以外の機能はありません)。

 import winsound
 winsound.Beep(17000, 100)

非常にシンプルで簡単ですが、Windowsでのみ利用できます。

だが:
この質問に対する完全な回答では、この方法では音が生成されますが、蚊を抑止しないことに注意してください。すでにテストされています: here および here を参照してください

15
tom10

プログラマーがコードがどのように機能するかを明確にするのに役立つので、ここにコードを入れています。説明はコード自体にあります:

#!/usr/bin/env python3
import pyaudio
import struct
import math

FORMAT = pyaudio.Paint16
CHANNELS = 2
RATE = 44100

p = pyaudio.PyAudio()


def data_for_freq(frequency: float, time: float = None):
    """get frames for a fixed frequency for a specified time or
    number of frames, if frame_count is specified, the specified
    time is ignored"""
    frame_count = int(RATE * time)

    remainder_frames = frame_count % RATE
    wavedata = []

    for i in range(frame_count):
        a = RATE / frequency  # number of frames per wave
        b = i / a
        # explanation for b
        # considering one wave, what part of the wave should this be
        # if we graph the sine wave in a
        # displacement vs i graph for the particle
        # where 0 is the beginning of the sine wave and
        # 1 the end of the sine wave
        # which part is "i" is denoted by b
        # for clarity you might use
        # though this is redundant since math.sin is a looping function
        # b = b - int(b)

        c = b * (2 * math.pi)
        # explanation for c
        # now we map b to between 0 and 2*math.PI
        # since 0 - 2*PI, 2*PI - 4*PI, ...
        # are the repeating domains of the sin wave (so the decimal values will
        # also be mapped accordingly,
        # and the integral values will be multiplied
        # by 2*PI and since sin(n*2*PI) is zero where n is an integer)
        d = math.sin(c) * 32767
        e = int(d)
        wavedata.append(e)

    for i in range(remainder_frames):
        wavedata.append(0)

    number_of_bytes = str(len(wavedata))  
    wavedata = struct.pack(number_of_bytes + 'h', *wavedata)

    return wavedata


def play(frequency: float, time: float):
    """
    play a frequency for a fixed time!
    """
    frames = data_for_freq(frequency, time)
    stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True)
    stream.write(frames)
    stream.stop_stream()
    stream.close()


if __name__ == "__main__":
    play(400, 1)
3
Aditya Shankar

SDLの Pythonバインディング を使用できます( Simple Direct Media Library )。

0
Monkey

私はPython3.6 +に対するjfsの回答を合理化し、いくつかのマイナーな改善を行いました:

import math
from pyaudio import PyAudio, paUInt8

def generate_sine_wave(frequency, duration, volume=0.2, sample_rate=22050):
    ''' Generate a tone at the given frequency.

        Limited to unsigned 8-bit samples at a given sample_rate.
        The sample rate should be at least double the frequency.
    '''
    if sample_rate < (frequency * 2):
        print('Warning: sample_rate must be at least double the frequency '
              f'to accurately represent it:\n    sample_rate {sample_rate}'
              f' ≯ {frequency*2} (frequency {frequency}*2)')

    num_samples = int(sample_rate * duration)
    rest_frames = num_samples % sample_rate

    pa = PyAudio()
    stream = pa.open(
        format=paUInt8,
        channels=1,  # mono
        rate=sample_rate,
        output=True,
    )

    # make samples
    s = lambda i: volume * math.sin(2 * math.pi * frequency * i / sample_rate)
    samples = (int(s(i) * 0x7F + 0x80) for i in range(num_samples))

    # write several samples at a time
    for buf in Zip( *([samples] * sample_rate) ):
        stream.write(bytes(buf))

    # fill remainder of frameset with silence
    stream.write(b'\x80' * rest_frames)

    stream.stop_stream()
    stream.close()
    pa.terminate()

generate_sine_wave(
    # see http://www.phy.mtu.edu/~suits/notefreqs.html
    frequency=523.25,   # Hz, waves per second C6
    duration=1.2,       # seconds to play sound
    volume=0.25,        # 0..1 how loud it is
    sample_rate=22050,  # number of samples per second: 11025, 22050, 44100
)
0
Gringo Suave

固定周波数のサウンドを再生する非常に簡単な方法もあります。

Winsound.beep(frequency, duration)

例えば:

winsound.beep(100, 0.5) 
0
Newton Yuan