Python: каковы ближайшие эквиваленты Linux и OSX от winsound.Beep?
Если вы хотите подать звуковой сигнал о динамике в Windows, Python 2, очевидно, обеспечивает полезную функцию: winsound.Beep()
. Оптимальная вещь об этой функции заключается в том, что она принимает аргументы, определяющие точную частоту и продолжительность звукового сигнала. Это именно то, что я хочу сделать, за исключением того, что я не использую Windows. Так что...
Каковы ближайшие эквиваленты winsound.Beep()
для Linux и OSX, привнося как можно меньше зависимостей?
Обратите внимание, что я хочу, чтобы вы могли напрямую подавать звуковой сигнал, а не воспроизводить звуковой файл. Кроме того, мне нужно иметь возможность контролировать частоту и продолжительность звукового сигнала, поэтому curses.beep()
и print '\a'
не будут работать. Наконец, я знаю, что PyGame предоставляет обширные звуковые возможности, но, учитывая, что я не требую каких-либо других функций PyGame, это похоже на использование кувалды, чтобы взломать орех (и в любом случае я пытаюсь избавиться от зависимостей насколько это возможно).
Ответы
Ответ 1
Я нашел здесь потенциальное решение:
http://bytes.com/topic/python/answers/25217-beeping-under-linux
Он включает в себя запись непосредственно в /dev/audio. Не уверен, насколько он переносится или даже работает вообще - я не на Linux-машине atm.
def beep(frequency, amplitude, duration):
sample = 8000
half_period = int(sample/frequency/2)
beep = chr(amplitude)*half_period+chr(0)*half_period
beep *= int(duration*frequency)
audio = file('/dev/audio', 'wb')
audio.write(beep)
audio.close()
Ответ 2
winsound только для окон, и я не мог найти кросс-платформенный способ сделать это, кроме print "/a". Однако вы не можете установить частоту и продолжительность с помощью этого.
Однако вы можете попробовать команду os.system сделать то же самое с системной командой beep. Вот фрагмент, который определяет функцию, которая имеет независимый от платформы способ
try:
import winsound
except ImportError:
import os
def playsound(frequency,duration):
#apt-get install beep
os.system('beep -f %s -l %s' % (frequency,duration))
else:
def playsound(frequency,duration):
winsound.Beep(frequency,duration)
Для получения дополнительной информации просмотрите этот блог
EDIT: вам нужно будет установить звуковой пакет на linux для запуска команды beep. Вы можете установить, указав команду
sudo apt-get install beep
Ответ 3
Самый легкий кросс-платформенный уровень, который я вижу, - "PortAudio". Это используется R, например, в их пакете, чтобы обернуть вызовы драйвера конкретной платформы в простой режим воспроизведения/записи оцифрованных осциллограмм в виде массива.
Хорошие люди в М.И.Т. создайте для этого привязку Python, но вам нужно будет включить скомпилированный .dll/.so для этого. http://people.csail.mit.edu/hubert/pyaudio/
(libao похож на Xiph создателей Ogg/Vorbis, существует оболочка pyao, но это кажется менее широко используемым)
SoX - отличный набор кросс-платформенных инструментов с гораздо большей функциональностью для преобразования формата и чтения файлов и т.д.
Использование ctypes для совершения звонков с Python на драйвер возможно, но очень грязно, даже простейшее унаследованное WinMM.
Ответ 4
Я нашел 3 метода для Linux:
- Новый метод с использованием API evdev Linux работает с любым пользователем в группе
input
(пример исходного кода)
- старый метод с использованием
fcntl
и /dev/console
(требует привилегий root) (пример исходного кода)
- вызвать команду
beep
непосредственно с помощью subprocess
или os.system
(медленнее и должно быть установлено в системе).
См. также моя функция tone() здесь со всеми альтернативами.
Ответ 5
Это работает на Mac:
import numpy as np
import simpleaudio as sa
def sound(x,z):
frequency = x # Our played note will be 440 Hz
fs = 44100 # 44100 samples per second
seconds = z # Note duration of 3 seconds
# Generate array with seconds*sample_rate steps, ranging between 0 and seconds
t = np.linspace(0, seconds, seconds * fs, False)
# Generate a 440 Hz sine wave
note = np.sin(frequency * t * 2 * np.pi)
# Ensure that highest value is in 16-bit range
audio = note * (2**15 - 1) / np.max(np.abs(note))
# Convert to 16-bit data
audio = audio.astype(np.int16)
# Start playback
play_obj = sa.play_buffer(audio, 1, 2, fs)
# Wait for playback to finish before exiting
play_obj.wait_done()
sound(300,2)
sound(200,1)