{"id":272,"date":"2014-01-03T22:01:37","date_gmt":"2014-01-03T21:01:37","guid":{"rendered":"http:\/\/www.opencloudblog.com\/?p=272"},"modified":"2021-01-17T13:18:16","modified_gmt":"2021-01-17T12:18:16","slug":"sound-generator-using-gnuradio","status":"publish","type":"post","link":"https:\/\/www.opencloudblog.com\/?p=272","title":{"rendered":"Sound generator using Gnuradio"},"content":{"rendered":"<p>Gnuradio is a powerful tool to process all sorts of signals using wave functions. This covers AM, FM, all sorts of modulation and much more.<\/p>\n<p>A simple starting point to play with Gnuradio is audio. It&#8217;s easy to built a tool to generate an audio tone, vary the frequency using a slider and output this using the soundcard of a PC.<\/p>\n<h2>Install Gnuradio<\/h2>\n<p>The first step is to install gnuradio and the necessary libraries. You should install gnuradio and all libgnuradio* libraries, and also libvolk.<\/p>\n<h2>Start Gnuradio Designer<\/h2>\n<p>The next step is to start Gnuradio designer<\/p>\n<pre class=\"lang:sh decode:true\" title=\"Start Gnuradio\">gnuradio-companion &amp;<\/pre>\n<p>The GUI has 3 areas. The large one is the area which shows the built signal flow, the area on the right are the components (blocks), which can be used. The area on the bottom is a message window.<\/p>\n<h2>Define the components<\/h2>\n<p>We need the following components to create our &#8222;sound generator&#8220;:<\/p>\n<ul>\n<li>A <strong>signal source<\/strong> from the sources block. This component has two input values, the amplitude and the frequency. Use the variables defined in the two widgets defined below.<\/li>\n<li>A <strong>WX GUI Slider<\/strong> from the WX GUI Widgets block to vary the frequency of the signal source. Default value=5000, min=10 and max=20000<\/li>\n<li>A\u00a0<strong>WX GUI Slider<\/strong>\u00a0from the WX GUI Widgets block to vary the amplitude of the signal source. Default value=0.7, min=0.0 and max=1.0<\/li>\n<li>A <strong>Noise Source<\/strong> from the sources block. This is added to create a more realistic scenario. Use the variable of the widget below.<\/li>\n<li>A\u00a0<strong>WX GUI Slider<\/strong>\u00a0from the WX GUI Widgets block to vary the amplitude of the noise source. Default value=0.01, min=0.0 and max=1.0<\/li>\n<li>An <strong>Add<\/strong> from the operators block. This is used to add the output from the signal source and the noise source.<\/li>\n<li>A <strong>Complex to Real<\/strong> conversion from the Type Conversions block. This is needed to feed real values to the sound sink. The input is connected to the add output.<\/li>\n<li>A <strong>Audio Sink<\/strong> from the Sinks block. This sends the output signal to the soundcard. The input is connected to the Complex to Real output.<\/li>\n<li>A graphical display <strong>WX GUI Waterfall Sink<\/strong> from the WX GUI Widgets block. This shows the time\/FFT spectrum. Set the FFT size to 2048.\u00a0The input is connected to the add output.<\/li>\n<li>A graphical display <strong>WX GUI FFT Sink<\/strong> from the WX GUI Widgtes block. This shows the FFT spectrum. Set the FFT size to 2048, peak hold to on and average alpha to 0.1 .\u00a0The input is connected to the add output.<\/li>\n<\/ul>\n<p>The variable samp_rate should be set to the highest possible value for your soundcard. Most modern PCs accept a sampling rate of 192000. Setting this to high values reduces distortions of the output signal.<\/p>\n<p>Now the signal flow area should look like the following screenshot:<\/p>\n<div id=\"attachment_276\" style=\"width: 577px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Audio.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-276\" class=\"size-medium wp-image-276\" alt=\"Gnuradio Soundgenerator\" src=\"http:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Audio-567x360.png\" width=\"567\" height=\"360\" srcset=\"https:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Audio-567x360.png 567w, https:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Audio-150x95.png 150w, https:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Audio.png 978w\" sizes=\"(max-width: 567px) 100vw, 567px\" \/><\/a><p id=\"caption-attachment-276\" class=\"wp-caption-text\">Gnuradio Soundgenerator<\/p><\/div>\n<p>&nbsp;<\/p>\n<p>Then you should save this setup using &#8222;save&#8220;. \u00a0If you do not like to create the generator by yourself, you can use the saved Gnuradio configuration file\u00a0<a href=\"http:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/frequency-test.txt\">frequency-generator.grc<\/a>.<\/p>\n<h2>Run the generator<\/h2>\n<p>Use Build &#8211;&gt; Execute to start the Sound generator. A new windows is opened, and you should now hear a tone (5000 Hz) out of the PC speaker\/headphone. The window looks like:<\/p>\n<div id=\"attachment_282\" style=\"width: 859px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Run.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-282\" class=\" wp-image-282 \" title=\"Gnuradio Run Window\" alt=\"Gnuradio Run Window\" src=\"http:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Run.png\" width=\"849\" height=\"674\" srcset=\"https:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Run.png 1061w, https:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Run-150x119.png 150w, https:\/\/www.opencloudblog.com\/wp-content\/uploads\/2014\/01\/Gnuradio-Run-453x360.png 453w\" sizes=\"(max-width: 849px) 100vw, 849px\" \/><\/a><p id=\"caption-attachment-282\" class=\"wp-caption-text\">Gnuradio Run Window<\/p><\/div>\n<p>The shown controls and graphics are:<\/p>\n<ul>\n<li>The slider <strong>Noise<\/strong> on the top defines the amplitude of the signal noise. Do not change it at the beginning.<\/li>\n<li>The second slider <strong>Loudness<\/strong> controls the amplitude of the audio signal source.<\/li>\n<li>The third slider <strong>Frequency<\/strong> is the real interesting one. If you move the slider slowly around, then the height of the tone changes.<\/li>\n<\/ul>\n<p>The two graphics show the FFT of the signals.<\/p>\n<p>Now it&#8217;s quite easy to extend the setup.<\/p>\n<h2>Python<\/h2>\n<p>When you select Build &#8211;&gt; Execute, GnuRadio generates a python script in the current directory with the name <strong>top_block.py<\/strong> . The code generated by Gnuradio from the example is:<\/p>\n<pre class=\"font:liberation-mono lang:python decode:true\" title=\"Python Code generated\">#!\/usr\/bin\/env python\r\n##################################################\r\n# Gnuradio Python Flow Graph\r\n# Title: Top Block\r\n# Generated: Fri Jan  3 21:21:14 2014\r\n##################################################\r\n\r\nfrom gnuradio import audio\r\nfrom gnuradio import eng_notation\r\nfrom gnuradio import gr\r\nfrom gnuradio import window\r\nfrom gnuradio.eng_option import eng_option\r\nfrom gnuradio.gr import firdes\r\nfrom gnuradio.wxgui import fftsink2\r\nfrom gnuradio.wxgui import forms\r\nfrom gnuradio.wxgui import waterfallsink2\r\nfrom grc_gnuradio import wxgui as grc_wxgui\r\nfrom optparse import OptionParser\r\nimport wx\r\n\r\nclass top_block(grc_wxgui.top_block_gui):\r\n\r\n        def __init__(self):\r\n                grc_wxgui.top_block_gui.__init__(self, title=\"Top Block\")\r\n                _icon_path = \"\/usr\/share\/icons\/hicolor\/32x32\/apps\/gnuradio-grc.png\"\r\n                self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))\r\n\r\n                ##################################################\r\n                # Variables\r\n                ##################################################\r\n                self.samp_rate = samp_rate = 192000\r\n                self.Noise = Noise = 0.01\r\n                self.Loudness = Loudness = 0.7\r\n                self.Frequency = Frequency = 5000\r\n\r\n                ##################################################\r\n                # Blocks\r\n                ##################################################\r\n                _Noise_sizer = wx.BoxSizer(wx.VERTICAL)\r\n                self._Noise_text_box = forms.text_box(\r\n                        parent=self.GetWin(),\r\n                        sizer=_Noise_sizer,\r\n                        value=self.Noise,\r\n                        callback=self.set_Noise,\r\n                        label=\"Noise\",\r\n                        converter=forms.float_converter(),\r\n                        proportion=0,\r\n                )\r\n                self._Noise_slider = forms.slider(\r\n                        parent=self.GetWin(),\r\n                        sizer=_Noise_sizer,\r\n                        value=self.Noise,\r\n                        callback=self.set_Noise,\r\n                        minimum=0.0,\r\n                        maximum=1,\r\n                        num_steps=1000,\r\n                        style=wx.SL_HORIZONTAL,\r\n                        cast=float,\r\n                        proportion=1,\r\n                )\r\n                self.Add(_Noise_sizer)\r\n                _Loudness_sizer = wx.BoxSizer(wx.VERTICAL)\r\n                self._Loudness_text_box = forms.text_box(\r\n                        parent=self.GetWin(),\r\n                        sizer=_Loudness_sizer,\r\n                        value=self.Loudness,\r\n                        callback=self.set_Loudness,\r\n                        label=\"Loudness\",\r\n                        converter=forms.float_converter(),\r\n                        proportion=0,\r\n                )\r\n                self._Loudness_slider = forms.slider(\r\n                        parent=self.GetWin(),\r\n                        sizer=_Loudness_sizer,\r\n                        value=self.Loudness,\r\n                        callback=self.set_Loudness,\r\n                        minimum=0.0,\r\n                        maximum=1.0,\r\n                        num_steps=1000,\r\n                        style=wx.SL_HORIZONTAL,\r\n                        cast=float,\r\n                        proportion=1,\r\n                )\r\n                self.Add(_Loudness_sizer)\r\n                _Frequency_sizer = wx.BoxSizer(wx.VERTICAL)\r\n                self._Frequency_text_box = forms.text_box(\r\n                        parent=self.GetWin(),\r\n                        sizer=_Frequency_sizer,\r\n                        value=self.Frequency,\r\n                        callback=self.set_Frequency,\r\n                        label=\"Frequency\",\r\n                        converter=forms.int_converter(),\r\n                        proportion=0,\r\n                )\r\n                self._Frequency_slider = forms.slider(\r\n                        parent=self.GetWin(),\r\n                        sizer=_Frequency_sizer,\r\n                        value=self.Frequency,\r\n                        callback=self.set_Frequency,\r\n                        minimum=10,\r\n                        maximum=20000,\r\n                        num_steps=1000,\r\n                        style=wx.SL_HORIZONTAL,\r\n                        cast=int,\r\n                        proportion=1,\r\n                )\r\n                self.Add(_Frequency_sizer)\r\n                self.wxgui_waterfallsink2_0 = waterfallsink2.waterfall_sink_c(\r\n                        self.GetWin(),\r\n                        baseband_freq=0,\r\n                        dynamic_range=100,\r\n                        ref_level=0,\r\n                        ref_scale=4.0,\r\n                        sample_rate=samp_rate,\r\n                        fft_size=2048,\r\n                        fft_rate=15,\r\n                        average=False,\r\n                        avg_alpha=0.1,\r\n                        title=\"Waterfall Plot\",\r\n                        size=(900,200),\r\n                )\r\n                self.Add(self.wxgui_waterfallsink2_0.win)\r\n                def wxgui_waterfallsink2_0_callback(x, y):\r\n                        self.set_Frequency(x)\r\n\r\n                self.wxgui_waterfallsink2_0.set_callback(wxgui_waterfallsink2_0_callback)\r\n                self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(\r\n                        self.GetWin(),\r\n                        baseband_freq=0,\r\n                        y_per_div=10,\r\n                        y_divs=10,\r\n                        ref_level=0,\r\n                        ref_scale=4.0,\r\n                        sample_rate=samp_rate,\r\n                        fft_size=2048,\r\n                        fft_rate=15,\r\n                        average=True,\r\n                        avg_alpha=0.1,\r\n                        title=\"FFT Plot\",\r\n                        peak_hold=True,\r\n                )\r\n                self.Add(self.wxgui_fftsink2_0.win)\r\n                self.gr_sig_source_x_2 = gr.sig_source_c(samp_rate, gr.GR_SIN_WAVE, Frequency, Loudness, 0)\r\n                self.gr_noise_source_x_0 = gr.noise_source_c(gr.GR_GAUSSIAN, Noise, 0)\r\n                self.gr_complex_to_real_0 = gr.complex_to_real(1)\r\n                self.gr_add_xx_1 = gr.add_vcc(1)\r\n                self.audio_sink_0 = audio.sink(samp_rate, \"\", True)\r\n\r\n                ##################################################\r\n                # Connections\r\n                ##################################################\r\n                self.connect((self.gr_complex_to_real_0, 0), (self.audio_sink_0, 0))\r\n                self.connect((self.gr_noise_source_x_0, 0), (self.gr_add_xx_1, 0))\r\n                self.connect((self.gr_sig_source_x_2, 0), (self.gr_add_xx_1, 1))\r\n                self.connect((self.gr_add_xx_1, 0), (self.gr_complex_to_real_0, 0))\r\n                self.connect((self.gr_add_xx_1, 0), (self.wxgui_waterfallsink2_0, 0))\r\n                self.connect((self.gr_add_xx_1, 0), (self.wxgui_fftsink2_0, 0))\r\n\r\n        def get_samp_rate(self):\r\n                return self.samp_rate\r\n\r\n        def set_samp_rate(self, samp_rate):\r\n                self.samp_rate = samp_rate\r\n                self.gr_sig_source_x_2.set_sampling_freq(self.samp_rate)\r\n                self.wxgui_fftsink2_0.set_sample_rate(self.samp_rate)\r\n                self.wxgui_waterfallsink2_0.set_sample_rate(self.samp_rate)\r\n\r\n        def get_Noise(self):\r\n                return self.Noise\r\n\r\n        def set_Noise(self, Noise):\r\n                self.Noise = Noise\r\n                self.gr_noise_source_x_0.set_amplitude(self.Noise)\r\n                self._Noise_slider.set_value(self.Noise)\r\n                self._Noise_text_box.set_value(self.Noise)\r\n\r\n        def get_Loudness(self):\r\n                return self.Loudness\r\n\r\n        def set_Loudness(self, Loudness):\r\n                self.Loudness = Loudness\r\n                self._Loudness_slider.set_value(self.Loudness)\r\n                self._Loudness_text_box.set_value(self.Loudness)\r\n                self.gr_sig_source_x_2.set_amplitude(self.Loudness)\r\n\r\n        def get_Frequency(self):\r\n                return self.Frequency\r\n\r\n        def set_Frequency(self, Frequency):\r\n                self.Frequency = Frequency\r\n                self._Frequency_slider.set_value(self.Frequency)\r\n                self._Frequency_text_box.set_value(self.Frequency)\r\n                self.gr_sig_source_x_2.set_frequency(self.Frequency)\r\n\r\nif __name__ == '__main__':\r\n        parser = OptionParser(option_class=eng_option, usage=\"%prog: [options]\")\r\n        (options, args) = parser.parse_args()\r\n        tb = top_block()\r\n        tb.Run(True)<\/pre>\n<p>If you save this code, there is no need to run the GnuRadio construction tool. GnuRadio provides a powerful python API.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gnuradio is a powerful tool to process all sorts of signals using wave functions. This covers AM, FM, all sorts of modulation and much more. A simple starting point to play with Gnuradio is audio. It&#8217;s easy to built a tool to generate an audio tone, vary the frequency using a slider and output this [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[],"_links":{"self":[{"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=\/wp\/v2\/posts\/272"}],"collection":[{"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=272"}],"version-history":[{"count":17,"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=\/wp\/v2\/posts\/272\/revisions"}],"predecessor-version":[{"id":293,"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=\/wp\/v2\/posts\/272\/revisions\/293"}],"wp:attachment":[{"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=272"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=272"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.opencloudblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=272"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}