首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于从终端窗口快速产生定制合成音调序列的Python方法

用于从终端窗口快速产生定制合成音调序列的Python方法
EN

Stack Overflow用户
提问于 2021-01-28 10:38:32
回答 2查看 50关注 0票数 2

我正在尝试设计一种快速生成音频信号的方法。我需要它进行电生理实验,在这些实验中,我将播放音调序列,以检查大脑听觉系统中的神经元反应。

我需要能够快速构建一个新的序列,其中我可以指定每个音调的特征(例如频率、持续时间、振幅等)、静默停顿(即休息)以及音调和停顿的序列。

我想在终端上使用一个简单的代码序列来做这件事。例如,输入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,但是还不清楚我如何或者是否可以使用这些方法来进行我所需要的快速的、基于终端的音频构造和回放。你有什么意见建议?

EN

回答 2

Stack Overflow用户

发布于 2021-01-30 04:08:16

这将是textX的初始解决方案:

代码语言:javascript
复制
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,轻松地从外部文件中获取输入食谱。

票数 2
EN

Stack Overflow用户

发布于 2021-01-28 14:59:15

这个带注释的pyparsing示例应该可以让您开始:

代码语言:javascript
复制
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))

它的工作原理:

代码语言:javascript
复制
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)

打印:

代码语言:javascript
复制
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上的模块参考

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65930261

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档