{"id":87067,"date":"2020-07-03T07:42:03","date_gmt":"2020-07-03T05:42:03","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-2"},"modified":"2020-07-03T07:42:03","modified_gmt":"2020-07-03T05:42:03","slug":"izuchaem-voip-dvizhok-mediastreamer2-chast-2","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-2","title":{"rendered":"Exploring the VoIP Engine Mediastreamer2. Part 2","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>The article material is taken from my <noindex><a rel=\"nofollow\" href=\"https:\/\/zen.yandex.ru\/id\/5e3f8e0751f5346faab4fc7a\">Zen channel<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Exploring the VoIP Engine Mediastreamer2. Part 2\" src=\"\/wp-content\/uploads\/2020\/07\/1afc1603a438f865c56bba72012d591e.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"sozdaem-tonalnyy-generator\">Creating a Tone Generator<\/h2>\n<p><\/p>\n<p>In the previous <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/495702\/\">article<\/a><\/noindex> we installed the Mediastreamer library, development tools, and tested their functionality by building a sample application.<\/p>\n<p><\/p>\n<p>Today, we will create an application that can emit a tone signal on the sound card. To achieve this, we need to connect the filters according to the sound generator scheme shown below:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Exploring the VoIP Engine Mediastreamer2. Part 2\" src=\"\/wp-content\/uploads\/2020\/07\/249759aec6235d3285e6ba6c28524710.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>We read the scheme from left to right; this is the direction in which our data flows. The arrows indicate this as well. The rectangles represent filters that process blocks of data and output the results. Inside each rectangle is its role, with the type of filter indicated in uppercase letters just below it. The arrows connecting the rectangles represent data queues through which data blocks are delivered from one filter to another. In general, a filter can have multiple inputs and outputs.<\/p>\n<p><\/p>\n<p>It all starts with a clock source that sets the tempo at which data is processed in the filters. With each clock pulse, every filter processes all the data blocks at its input and outputs the result blocks into the queue. First, the closest filter to the clock source processes, followed by filters connected to its outputs (there can be many outputs), and so on. After the last filter in the chain finishes processing, the execution stops until a new clock pulse arrives. By default, clock pulses occur at intervals of 10 milliseconds. <\/p>\n<p><\/p>\n<p>Let's return to our scheme. The pulses are fed into the silence source, which is a filter that generates a block of data containing zeros at each pulse on its output. If we consider this block as a block of sound samples, it is nothing other than silence. At first glance, it seems strange to generate data blocks of silence\u2014after all, it cannot be heard\u2014but these blocks are necessary for the operation of the sound signal generator. The generator uses these blocks as a blank sheet of paper, writing sound samples into them. In its normal state, the generator is turned off and simply passes the input blocks to the output. Thus, the silence blocks pass unchanged through the entire scheme from left to right, reaching the sound card, which silently takes the blocks from the queue connected to its input.<\/p>\n<p><\/p>\n<p>But everything changes when the generator receives a command to play sound; it starts generating sound samples, replacing them in the input blocks and outputting the modified blocks. The sound card begins to produce sound. Below is the program that implements the scheme described above:<\/p>\n<p><\/p>\n<pre><code class=\"cpp\">\/* \u0424\u0430\u0439\u043b mstest2.c *\/\n#include &lt;mediastreamer2\/msfilter.h&gt;\n#include &lt;mediastreamer2\/msticker.h&gt;\n#include &lt;mediastreamer2\/dtmfgen.h&gt;\n#include &lt;mediastreamer2\/mssndcard.h&gt;\nint main()\n{\n    ms_init();\n\n    \/* \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. *\/\n    MSFilter  *voidsource = ms_filter_new(MS_VOID_SOURCE_ID);\n    MSFilter  *dtmfgen = ms_filter_new(MS_DTMF_GEN_ID);\n    MSSndCard *card_playback = ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());\n    MSFilter  *snd_card_write = ms_snd_card_create_writer(card_playback);\n\n    \/* \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0442\u0438\u043a\u0435\u0440. *\/\n    MSTicker *ticker = ms_ticker_new();\n\n    \/* \u0421\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0443. *\/\n    ms_filter_link(voidsource, 0, dtmfgen, 0);\n    ms_filter_link(dtmfgen, 0, snd_card_write, 0);\n\n   \/* \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0442\u0430\u043a\u0442\u043e\u0432. *\/\n   ms_ticker_attach(ticker, voidsource);\n\n   \/* \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0432\u0443\u043a\u043e\u0432\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440. *\/\n   char key='1';\n   ms_filter_call_method(dtmfgen, MS_DTMF_GEN_PLAY, (void*)&amp;key);\n\n   \/* \u0414\u0430\u0435\u043c, \u0432\u0440\u0435\u043c\u044f, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0431\u043b\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u044b\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u0437\u0432\u0443\u043a\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u043e\u0439.*\/\n   ms_sleep(2);   \n}<\/code><\/pre>\n<p><\/p>\n<p>After initializing the media streamer, three filters are created: <em>voidsource, dtmfgen, snd_card_write<\/em>. A clock signal source is created.<\/p>\n<p><\/p>\n<p>Then, the filters need to be connected according to our schematic, with the clock source being connected last, as the circuit will start operating immediately thereafter. If the clock source is connected to an unfinished circuit, there is a risk that the media streamer will crash if it detects even one filter in the chain with all inputs or outputs \"hanging in the air\" (not connected). <\/p>\n<p><\/p>\n<p>Connecting the filters is done using the function <\/p>\n<p><\/p>\n<pre><code class=\"cpp\">ms_filter_link(src, src_out, dst, dst_in)<\/code><\/pre>\n<p><\/p>\n<p>where the first argument is a pointer to the source filter, the second argument is the output number of the source (note that inputs and outputs are numbered starting from zero). The third argument is a pointer to the receiving filter, and the fourth is the input number of the receiver.<\/p>\n<p><\/p>\n<p>All filters are connected and the clock source is the last to connect (hereafter we will simply call it the ticker). After that, our audio scheme is activated, but there is still no sound from the computer's speakers \u2014 the sound generator is off and simply passes the input data blocks with silence. To start generating a tonal signal, the generator's filter method needs to be executed.<\/p>\n<p><\/p>\n<p>We will generate a dual-tone (DTMF) signal corresponding to pressing the \"1\" button on the phone. For this, we will use a function <em>ms_filter_call_method()<\/em> to call the method MS_DTMF_GEN_PLAY, passing as an argument a pointer to the code corresponding to the signal to be played.<\/p>\n<p><\/p>\n<p>Now it's time to compile the program:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ gcc mstest2.c -o mstest2 `pkg-config mediastreamer --libs --cflags`<\/code><\/pre>\n<p><\/p>\n<p>And run it:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ .\/mstest2<\/code><\/pre>\n<p><\/p>\n<p>After starting the program, you will hear a short sound signal consisting of two tones through the computer's speakers.<\/p>\n<p><\/p>\n<p>We constructed and launched our first audio scheme. We saw how to create filter instances, how to connect them, and how to call their methods. Having celebrated our first success, we still need to pay attention to the fact that our program does not free the allocated memory before finishing. In the next <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/495780\/\">article<\/a><\/noindex> we will learn to clean up after ourselves.<\/p>\n<p>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/495728\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0437\u044f\u0442 \u0441 \u043c\u043e\u0435\u0433\u043e \u0434\u0437\u0435\u043d-\u043a\u0430\u043d\u0430\u043b\u0430. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0442\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0441\u0442\u0440\u0438\u043c\u0435\u0440\u0430, \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b\u0438 \u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0441\u043e\u0431\u0440\u0430\u0432 \u043f\u0440\u043e\u0431\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u043f\u0438\u043b\u0438\u043a\u0430\u0442\u044c \u043d\u0430 \u0437\u0432\u0443\u043a\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u0435 \u0442\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0438\u0433\u043d\u0430\u043b. \u0427\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0432 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u0443\u044e \u043d\u0438\u0436\u0435 \u0441\u0445\u0435\u043c\u0443 \u0437\u0432\u0443\u043a\u043e\u0432\u043e\u0433\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430: \u0427\u0438\u0442\u0430\u0435\u043c \u0441\u0445\u0435\u043c\u0443 \u0441\u043b\u0435\u0432\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":87068,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-87067","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0437\u044f\u0442 \u0441 \u043c\u043e\u0435\u0433\u043e \u0434\u0437\u0435\u043d-\u043a\u0430\u043d\u0430\u043b\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-2\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0418\u0437\u0443\u0447\u0430\u0435\u043c VoIP-\u0434\u0432\u0438\u0436\u043e\u043a Mediastreamer2. \u0427\u0430\u0441\u0442\u044c 2 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0437\u044f\u0442 \u0441 \u043c\u043e\u0435\u0433\u043e \u0434\u0437\u0435\u043d-\u043a\u0430\u043d\u0430\u043b\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-2\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-03T05:42:03+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-03T05:42:03+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Exploring the VoIP engine Mediastreamer2. Part 2 | ProHoster","description":"The content of the article is taken from my Zen channel.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-2","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0418\u0437\u0443\u0447\u0430\u0435\u043c VoIP-\u0434\u0432\u0438\u0436\u043e\u043a Mediastreamer2. \u0427\u0430\u0441\u0442\u044c 2 | ProHoster","og:description":"\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0437\u044f\u0442 \u0441 \u043c\u043e\u0435\u0433\u043e \u0434\u0437\u0435\u043d-\u043a\u0430\u043d\u0430\u043b\u0430.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/izuchaem-voip-dvizhok-mediastreamer2-chast-2","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-03T05:42:03+00:00","article:modified_time":"2020-07-03T05:42:03+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"87067","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:59:55","updated":"2022-10-04 22:45:55","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/87067","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=87067"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/87067\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/87068"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=87067"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=87067"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=87067"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}