wbserver roundSlider小部件无法启动/更新音频程序

时间:2019-08-01 14:53:36

标签: python webserver

我有一个导入到Falsk Web服务器中的“拨号音” python程序,并且我有一个html嵌入式roundSlider小部件,我试图使用它来更新拨号音程序中的采样率变量值。一旦我运行了网络服务器并开始拖动滑块,就可以看到滑块的值在拖动时确实会更新/更改,但是没有提示音,提示音程序不会启动!

请,我需要您的帮助来解决这个问题。

这是我的烧瓶app.py:

from flask import Flask, render_template, jsonify, request,redirect,url_for
from random import randint
from top_block_22 import top_block_22

app = Flask(__name__)
# def test():
#     print("its working") 
@app.route('/')
def slide_func():
    return render_template("index.html")
    print(slide_val)
    return(slide_val)
def test():
    print("its working")

@app.route('/valueofslider')
def slide():
    slide_val = request.args.get('slide_val')
    return main(slide_val)   

def main(slide_val):

    tb = top_block_22()
    tb.start()
    samp_rate = int(slide_val) + 100
    print(samp_rate)
    return(slide_val)  
    app.debug = True
if __name__ == '__main__':
    app.run(debug=True)

主拨号音代码:

from gnuradio import analog
from gnuradio import audio

from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser
from flask import Flask, render_template, jsonify, request, redirect, url_for
from random import randint
#from app import *





class top_block_22(gr.top_block):

    def __init__(self, samp_rate):

        gr.top_block.__init__(self, "Top Block 22")        
        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 32000

        ##################################################
        # Blocks
        ##################################################
        self.blocks_add_xx = blocks.add_vff(1)
        self.audio_sink = audio.sink(32000, '', True)
        self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 440, 0.4, 0)
        self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 350, 0.4, 0)
        self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, 0.005, -42)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx, 2))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx, 0))
        self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx, 1))
        self.connect((self.blocks_add_xx, 0), (self.audio_sink, 0))



def main(top_block_cls=top_block_22, options=None):


    tb = top_block_22('samp_rate')

    tb.start()
    try:
        raw_input('Press Enter to quit: ')
    except EOFError:
        pass
    tb.stop()
    tb.wait()


if __name__ == '__main__':
        main()

index.html脚本:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery roundSlider - JS Bin</title>
  <link rel="icon" href="data:,">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.css" rel="stylesheet" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.js"></script>
</head>
<body>
  <!-- Only html needed   -->
<form class="form-inline" method="POST" action="{{ url_for('slide') }}">
  <div id="slider"></div>

  <script>
    var val;
    $("#slider").roundSlider({
      radius: 215,
        min: 0,
        max: 100000,
       change: function () {

        var obj1 = $("#slider").data("roundSlider");
        val = obj1.getValue();
        value: 10
        $.getJSON('/valueofslider', {
          slide_val: val
        });
      }
    });
  </script>
</body>
</html>

这是滑块更新其值时的图像:

slider

1 个答案:

答案 0 :(得分:1)

此代码对我有用。

主要问题是该函数运行得如此之快,以至于没人能听到声音-因此我添加了time.sleep(0.5)

我将所有代码都放在一个文件中,这样可以更轻松地将其复制并粘贴到文件中以运行它。

主页http://localhost:5000/上仅显示几个具有不同值的链接以对其进行测试。

from gnuradio import analog
from gnuradio import audio

from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser


class top_block_22(gr.top_block):

    def __init__(self, samp_rate=32000): # default value for samp_rate

        gr.top_block.__init__(self, "Top Block 22")        
        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate   # without "= 32000"
        print('[DEBUG] top_block_22:', self.samp_rate)

        ##################################################
        # Blocks
        ##################################################
        self.blocks_add_xx = blocks.add_vff(1)
        self.audio_sink = audio.sink(32000, '', True)
        self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 440, 0.4, 0)
        self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 350, 0.4, 0)
        self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, 0.005, -42)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx, 2))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx, 0))
        self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx, 1))
        self.connect((self.blocks_add_xx, 0), (self.audio_sink, 0))

# -----------------------------------------------------------------------------

from flask import Flask, request
#from top_block_22 import top_block_22 
import time


app = Flask(__name__)


@app.route('/')
def index():
    HTML = 'HEAR:'
    for item in (20000, 25000, 32000):
        HTML += ' <a href="/valueofslider?slide_val={}">{}</a>'.format(item, item)
    return HTML

@app.route('/valueofslider')
def slide():
    slide_val = request.args.get('slide_val', 32000) # default value 32000
    main(slide_val)
    return slide_val

def main(slide_val):
    samp_rate = int(slide_val) + 100
    print('[DEBUG] main:', samp_rate)

    tb = top_block_22(samp_rate) # run with value from variable
    tb.start()

    time.sleep(0.5)

    tb.stop()
    tb.wait()


if __name__ == '__main__':    
    app.run(debug=True)

编辑:此版本显示滑块,并且始终使用Thread播放声音(在滑块上选择第一个值之后)。

当滑块发送新值时,它将停止旧线程并使用新的samp_rate创建一个新线程。

但是也许可以不用Thread而只使用tb.starttb.stop等来完成。看来top_block_22已经使用线程了。

它还使用http://localhost:5000/off发送samp_rate=0来停止声音。

from gnuradio import analog
from gnuradio import audio

from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser


class top_block_22(gr.top_block):

    def __init__(self, samp_rate):

        gr.top_block.__init__(self, "Top Block 22")        
        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate
        print('[DEBUG] top_block_22:', self.samp_rate)

        ##################################################
        # Blocks
        ##################################################
        self.blocks_add_xx = blocks.add_vff(1)
        self.audio_sink = audio.sink(32000, '', True)
        self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 440, 0.4, 0)
        self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 350, 0.4, 0)
        self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, 0.005, -42)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx, 2))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx, 0))
        self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx, 1))
        self.connect((self.blocks_add_xx, 0), (self.audio_sink, 0))

# -----------------------------------------------------------------------------

from threading import Thread

class MyThread(Thread):

    def __init__(self, samp_rate):
        Thread.__init__(self)
        self.running = True
        self.samp_rate = samp_rate

    def run(self):

        tb = top_block_22(self.samp_rate)
        tb.start()

        while self.running:
            time.sleep(0.5)  # need it to head sound

        tb.stop()
        tb.wait()

# -----------------------------------------------------------------------------

from flask import Flask, request
#from top_block_22 import top_block_22 
import time


app = Flask(__name__)

my_thread = None


@app.route('/')
def index():
    return '''<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery roundSlider - JS Bin</title>
  <link rel="icon" href="data:,">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.css" rel="stylesheet" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.js"></script>
</head>
<body>
  <!-- Only html needed   -->
<form class="form-inline" method="POST" action="{{ url_for('slide') }}">
  <div id="slider"></div>

  <script>
    var val;
    $("#slider").roundSlider({
      radius: 215,
        min: 0,
        max: 100000,
       change: function () {

        var obj1 = $("#slider").data("roundSlider");
        val = obj1.getValue();
        value: 10
        $.getJSON('/valueofslider', {
          slide_val: val
        });
      }
    });
  </script>
</body>
</html>'''

@app.route('/off')
def off():
    '''use `slide_val=0` to turn it off'''
    main(0)
    return 'off'

@app.route('/valueofslider')
def slide():
    slide_val = request.args.get('slide_val', 32000)
    main(slide_val)
    return slide_val

def main(slide_val):
    global my_thread

    print('[DEBUG] main:', slide_val)
    samp_rate = int(slide_val)

    if my_thread: # if my_thread is not None
        my_thread.running = False
        my_thread.join()
        my_thread = None

    if samp_rate > 0:
        my_thread = MyThread(samp_rate)
        my_thread.start()


if __name__ == '__main__':    
    app.run(debug=True)

编辑:不带Thread的版本。

和以前一样,它显示滑块,并且在选择第一个值后一直播放声音。它使用全局值tb来保持对对象的访问,并在获取新的samp_rate时停止它,并运行新对象。

它还使用http://localhost:5000/off发送samp_rate=0来停止声音。

from gnuradio import analog
from gnuradio import audio

from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser


class top_block_22(gr.top_block):

    def __init__(self, samp_rate):

        gr.top_block.__init__(self, "Top Block 22")        
        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate
        print('[DEBUG] top_block_22:', self.samp_rate)

        ##################################################
        # Blocks
        ##################################################
        self.blocks_add_xx = blocks.add_vff(1)
        self.audio_sink = audio.sink(32000, '', True)
        self.analog_sig_source_x_1 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 440, 0.4, 0)
        self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, 350, 0.4, 0)
        self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, 0.005, -42)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx, 2))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx, 0))
        self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx, 1))
        self.connect((self.blocks_add_xx, 0), (self.audio_sink, 0))

# -----------------------------------------------------------------------------

from flask import Flask, request
#from top_block_22 import top_block_22 


app = Flask(__name__)

tb = None  # global variable to keep it between requests


@app.route('/')
def index():
    return '''<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery roundSlider - JS Bin</title>
  <link rel="icon" href="data:,">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.css" rel="stylesheet" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.js"></script>
</head>
<body>
  <!-- Only html needed   -->
<form class="form-inline" method="POST" action="{{ url_for('slide') }}">
  <div id="slider"></div>

  <script>
    var val;
    $("#slider").roundSlider({
      radius: 215,
        min: 0,
        max: 100000,
       change: function () {

        var obj1 = $("#slider").data("roundSlider");
        val = obj1.getValue();
        value: 10
        $.getJSON('/valueofslider', {
          slide_val: val
        });
      }
    });
  </script>
</body>
</html>'''

@app.route('/off')
def off():
    '''use `slide_val=0` to turn it off'''
    main(0)
    return 'off'

@app.route('/valueofslider')
def slide():
    slide_val = request.args.get('slide_val', 32000)
    main(slide_val)
    return slide_val

def main(slide_val):
    global tb

    print('[DEBUG] main:', slide_val)
    samp_rate = int(slide_val)

    # stop old sound
    if tb: # if tb is not None
        tb.stop()
        tb.wait()
        tb = None 

    # create new sound (if not zero)
    if samp_rate > 0:
        tb = top_block_22(samp_rate)
        tb.start()


if __name__ == '__main__':    
    app.run(debug=True)

编辑:最新版本

JavaScript的一些变化:

  • 它在开始时设置默认值-32000。JS中有错误。
  • 它在开始时发送请求,因此它在加载页面后开始发出声音。无需在滑块上选择值。

Python中的更改:

  • 建议PEP 8 -- Style Guide for Python Code我将UpperCaseName设置为课程-TopBlock22
  • main重命名为sound,以更好地描述函数的作用
  • http://localhost/set/<value>设置采样率,以便可以代替http://localhost/valueofslider?slider_val=<value>使用它。
  • http://localhost/get获取当前采样率
  • http://localhost/off将value设置为0,以便关闭声音。当它太烦人时,我用它来快速关闭声音。
  • print_function来自__future__,像Python 3一样使用print(text)
  • 函数以文本形式返回值,但是带有jsonify()的行,因此它们可以将其作为JSON重新调整。也许以后会有用。

FAQ中,我发现了How can I reconfigure a flow graph? How do I use lock(), unlock()?,所以也许它可以更改采样率而无需创建新对象,并且它可以提供更好的声音。当它更改采样率时,我会先单击。

代码:

from __future__ import print_function

from gnuradio import analog
from gnuradio import audio

from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser


class TopBlock22(gr.top_block): # PEP8: CamelCaseName for classes

    def __init__(self, sample_rate=32000):

        gr.top_block.__init__(self, "Top Block 22")        
        ##################################################
        # Variables
        ##################################################
        self.sample_rate = sample_rate
        print('[TopBlock22] sample_rate:', self.sample_rate)

        ##################################################
        # Blocks
        ##################################################
        self.blocks_add_xx = blocks.add_vff(1)
        self.audio_sink = audio.sink(32000, '', True)
        self.analog_sig_source_x_1 = analog.sig_source_f(sample_rate, analog.GR_COS_WAVE, 440, 0.4, 0)
        self.analog_sig_source_x_0 = analog.sig_source_f(sample_rate, analog.GR_COS_WAVE, 350, 0.4, 0)
        self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, 0.005, -42)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx, 2))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx, 0))
        self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx, 1))
        self.connect((self.blocks_add_xx, 0), (self.audio_sink, 0))

# -----------------------------------------------------------------------------

from flask import Flask, request, jsonify
#from top_block_22 import TopBlock22 
import time


app = Flask(__name__)

tb = None  # global variable to keep it between requests


@app.route('/')
def index():
    return '''<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>GNURadio Slider Example</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.css" rel="stylesheet" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.js"></script>
</head>
<body>

<div id="slider"></div>

<script>

  // keep slider's value
  var val;

  // create slider
  $("#slider").roundSlider({
    radius: 215,
    min: 0,
    max: 100000,
    value: 32000, // default value at start
    change: function () {
      var obj = $("#slider").data("roundSlider");
      val = obj.getValue();
      $.getJSON('/valueofslider', {
        slide_val: val
      });
    }
  });

  // play sound at start
  $.getJSON('/valueofslider', {slide_val: val});

</script>

</body>
</html>'''

@app.route('/test')
def test():
    HTML = 'HEAR:'
    for item in (0, 10000, 20000, 25000, 32000):
        HTML += ' <a href="/set/{}">{}</a>'.format(item, item)
    return HTML

@app.route('/off')
def off():
    """Turn off sound."""
    sound(0)
    #return jsonify({'val': 0})
    return 'off'

@app.route('/set/<int:value>')
def set_value(value):
    """Set value. Use 0 to turn it off."""
    sound(value)
    #return jsonify({'val': value})
    return str(value)

@app.route('/get')
def get_value():
    """Get current value."""
    if tb:
        value = tb.sample_rate
    else:
        value = 0
    #return jsonify({'val': value})
    return str(value)

@app.route('/valueofslider')
def slide():
    sample_rate = request.args.get('slide_val', '32000')
    sample_rate = int(sample_rate)
    sound(sample_rate)
    #return jsonify({'val': sample_rate})
    return str(sample_rate)

def sound(sample_rate):
    global tb

    print('[sound] sample_rate:', sample_rate)
    sample_rate = int(sample_rate)

    # stop old sound
    if tb: # if tb is not None
        tb.stop()
        tb.wait()
        tb = None 

    # create new sound (if not zero)
    if sample_rate > 0:
        tb = TopBlock22(sample_rate)
        tb.start()


if __name__ == '__main__':    
    app.run(debug=True)

编辑:这次是上一版本。

它使用lock/unlockdisconnect/connect更改声音而无需创建新对象。根据常见问题解答(How can I reconfigure a flow graph? How do I use lock(), unlock()?)中的示例,但是disconnect需要两个端点,例如connect

from __future__ import print_function

from gnuradio import analog
from gnuradio import audio

from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser


class TopBlock22(gr.top_block): # PEP8: CamelCaseName for classes

    def __init__(self, sample_rate=32000):

        gr.top_block.__init__(self, "Top Block 22")        
        ##################################################
        # Variables
        ##################################################
        self.sample_rate = sample_rate
        print('[TopBlock22] __init__: sample_rate:', self.sample_rate)

        ##################################################
        # Blocks
        ##################################################
        self.blocks_add_xx = blocks.add_vff(1)
        self.audio_sink = audio.sink(32000, '', True)
        self.analog_sig_source_x_1 = analog.sig_source_f(sample_rate, analog.GR_COS_WAVE, 440, 0.4, 0)
        self.analog_sig_source_x_0 = analog.sig_source_f(sample_rate, analog.GR_COS_WAVE, 350, 0.4, 0)
        self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, 0.005, -42)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx, 2))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx, 0))
        self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx, 1))
        self.connect((self.blocks_add_xx, 0), (self.audio_sink, 0))

    def change(self, sample_rate):
        self.sample_rate = sample_rate
        print('[TopBlock22] change: sample_rate:', self.sample_rate)

        # lock
        self.lock()

        # disconect - needs two endpoints (not like in FAQ)
        self.disconnect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx, 0))
        self.disconnect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx, 1))

        # create new
        self.analog_sig_source_x_1 = analog.sig_source_f(sample_rate, analog.GR_COS_WAVE, 440, 0.4, 0)
        self.analog_sig_source_x_0 = analog.sig_source_f(sample_rate, analog.GR_COS_WAVE, 350, 0.4, 0)

        # connect again
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_xx, 0))
        self.connect((self.analog_sig_source_x_1, 0), (self.blocks_add_xx, 1))

        # unlock
        self.unlock()

# -----------------------------------------------------------------------------

from flask import Flask, request, jsonify


app = Flask(__name__)

tb = None  # global variable to keep it between requests


@app.route('/')
def index():
    return '''<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>GNURadio Slider Example</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.css" rel="stylesheet" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/roundSlider/1.3.2/roundslider.min.js"></script>
</head>
<body>

<div id="slider"></div>

<script>

  // keep slider's value
  var val;

  // create slider
  $("#slider").roundSlider({
    radius: 215,
    min: 0,
    max: 100000,
    value: 32000, // default value at start
    change: function () {
      var obj = $("#slider").data("roundSlider");
      val = obj.getValue();
      $.getJSON('/valueofslider', {
        slide_val: val
      });
    }
  });

  // play sound at start
  $.getJSON('/valueofslider', {slide_val: val});

</script>

</body>
</html>'''

@app.route('/test')
def test():
    HTML = 'HEAR:'
    for item in (0, 10000, 20000, 25000, 32000):
        HTML += ' <a href="/set/{}">{}</a>'.format(item, item)
    return HTML

@app.route('/off')
def off():
    """Turn off sound."""
    sound(0)
    #return jsonify({'val': 0})
    return 'off'

@app.route('/set/<int:value>')
def set_value(value):
    """Set value. Use 0 to turn it off."""
    sound(value)
    #return jsonify({'val': value})
    return str(value)

@app.route('/get')
def get_value():
    """Get value. Returns 0 when turned off."""
    if tb:
        value = tb.sample_rate
    else:
        value = 0
    #return jsonify({'val': value})
    return str(value)

@app.route('/valueofslider')
def slide():
    sample_rate = request.args.get('slide_val', '32000')
    sample_rate = int(sample_rate)
    sound(sample_rate)
    #return jsonify({'val': sample_rate})
    return str(sample_rate)

def sound_old(sample_rate):
    """version which doesn't use `change()`"""
    global tb

    print('[sound] sample_rate:', sample_rate)
    sample_rate = int(sample_rate)

    # stop old sound
    if tb: # if tb is not None
        tb.stop()
        tb.wait()
        tb = None 

    # create new sound (if not zero)
    if sample_rate > 0:
        tb = TopBlock22(sample_rate)
        tb.start()

def sound(sample_rate):
    """version which uses `change()`"""
    global tb

    print('[sound] sample_rate:', sample_rate)
    sample_rate = int(sample_rate)

    # change or stop old sound
    if tb: # if tb is not None
        if sample_rate > 0:
            tb.change(sample_rate)
        else:        
            tb.stop()
            tb.wait()
            tb = None 

    # create new sound (if not zero)
    if not tb:
        if sample_rate > 0:
            tb = TopBlock22(sample_rate)
            tb.start()


if __name__ == '__main__':    
    app.run(debug=True)

编辑:我发现sample rate可以通过

进行更改
 self.analog_sig_source_x_1.set_sampling_freq(sample_rate)

因此不必创建新的sig_source_f

class TopBlock22(gr.top_block):

    # ... rest ...

    def change(self, sample_rate):
        self.sample_rate = sample_rate
        print('[TopBlock22] change: sample_rate:', self.sample_rate)

        self.analog_sig_source_x_1.set_sampling_freq(sample_rate)
        self.analog_sig_source_x_0.set_sampling_freq(sample_rate)

我认为现在sample rate更改时我听不到点击声,但是现在填充鼠标单击后才有一点延迟。

要查看此对象中的其他功能,可以使用dir(self.analog_sig_source_x_1)

    print('\n'.join(dir(self.analog_sig_source_x_1)))

    ...        
    set_amplitude
    set_block_alias
    set_frequency
    set_max_noutput_items
    set_max_output_buffer
    set_min_noutput_items
    set_min_output_buffer
    set_offset
    set_processor_affinity
    set_sampling_freq
    set_thread_priority
    set_waveform
    ...

资料来源:Choosing, defining and configuring blocksdocumentation for C/C++ version