我正在尝试设计一种快速生成音频信号的方法。我需要它进行电生理实验,在这些实验中,我将播放音调序列,以检查大脑听觉系统中的神经元反应。
我需要能够快速构建一个新的序列,其中我可以指定每个音调的特征(例如频率、持续时间、振幅等)、静默停顿(即休息)以及音调和停顿的序列。
我想在终端上使用一个简单的代码序列来做这件事。例如,输入tone(440,2) rest(2) tone(880,1) rest(1) tone(880,1)将生成一首“歌曲”,它以440 Hz的频率播放2秒的正弦波音,然后是2秒的休息,然后是1秒的880 Hz的音调,依此类推。
我有用于产生音调和休息的Python函数,但我不知道如何从终端访问和控制它们来实现此目的。经过一些阅读,似乎使用textX或PyParsing可能是不错的选择,但我没有创建特定于领域的语言或解析器的背景,所以我不确定。我已经完成了这篇textX tutorial并阅读了这篇PyParsing description,但是还不清楚我如何或者是否可以使用这些方法来进行我所需要的快速的、基于终端的音频构造和回放。你有什么意见建议?
发布于 2021-01-30 04:08:16
这将是textX的初始解决方案:
from textx import metamodel_from_str
grammar = r'''
Commands: commands*=Command;
Command: Tone | Rest;
Tone: 'tone' '(' freq=INT ',' duration=INT ')';
Rest: 'rest' '(' duration=INT ')';
'''
mm = metamodel_from_str(grammar)
input = 'tone(440,2) rest(2) tone(880,1) rest(1) tone(880,1)'
model = mm.model_from_str(input)
for command in model.commands:
if command.__class__.__name__ == 'Tone':
# This command is a tone. Call your function for tone. For example:
render_tone(command.freq, command.duration)
else:
# Call rest. For example:
render_rest(command.duration)您还可以通过将上面的mm.model_from_str更改为mm.model_from_file,轻松地从外部文件中获取输入食谱。
发布于 2021-01-28 14:59:15
这个带注释的pyparsing示例应该可以让您开始:
import pyparsing as pp
ppc = pp.pyparsing_common
# expressions for punctuation - useful during parsing, but
# should be suppressed from the parsed results
LPAR, RPAR, COMMA = map(pp.Suppress, "(),")
# expressions for your commands and numeric values
# the value expression could have used ppc.integer, but
# using number allows for floating point values (such as
# durations that are less than a second)
TONE = pp.Keyword("tone")
REST = pp.Keyword("rest")
value = ppc.number
# expressions for tone and rest commands
tone_expr = (TONE("cmd")
+ LPAR + value("freq") + COMMA + value("duration") + RPAR)
rest_expr = (REST("cmd")
+ LPAR + value("duration") + RPAR)
# a command is a tone or a rest expression
cmd_expr = tone_expr | rest_expr
# functions to call for each command - replace with your actual
# music functions
def play_tone(freq, dur):
print("BEEP({}, {})".format(freq, dur))
def play_rest(dur):
print("REST({})".format(dur))它的工作原理:
cmd_str = "tone(440,0.2) rest(2) tone(880, 1) rest(1) tone( 880, 1 )"
for music_code in cmd_expr.searchString(cmd_str):
if music_code.cmd == "tone":
play_tone(music_code.freq, music_code.duration)
elif music_code.cmd == "rest":
play_rest(music_code.duration)
else:
print("unexpected code", music_code.cmd)打印:
BEEP(440, 0.2)
REST(2)
BEEP(880, 1)
REST(1)
BEEP(880, 1)https://pyparsing-docs.readthedocs.io/en/pyparsing_2.4.7/HowToUsePyparsing.html上的更多信息和https://pyparsing-docs.readthedocs.io/en/pyparsing_2.4.7/pyparsing.html上的模块参考
https://stackoverflow.com/questions/65930261
复制相似问题