{"id":6412,"date":"2024-10-21T16:18:58","date_gmt":"2024-10-21T14:18:58","guid":{"rendered":"https:\/\/www.pschatzmann.ch\/home\/?p=6412"},"modified":"2024-10-23T09:15:20","modified_gmt":"2024-10-23T07:15:20","slug":"a-new-architechture-for-talkie-talkiepcm","status":"publish","type":"post","link":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/","title":{"rendered":"A new Architechture for Talkie: TalkiePCM"},"content":{"rendered":"<p>There are quite a few <strong>popular TTS libraries for Arduino<\/strong> but most of them suffer from the <strong>same problem<\/strong>: The <strong>TTS function is not properly separated from the output function<\/strong>.<\/p>\n<h2>Architechture<\/h2>\n<p>In a properly architected solution we would have a<\/p>\n<ul>\n<li>A <strong>TTS function<\/strong> which produces platfrom independent PCM data<\/li>\n<li>An <strong>output function or library<\/strong> to process the PCM data.<\/li>\n<\/ul>\n<p>In <strong>Arduino<\/strong> we have the abstact <strong>Print class<\/strong> which is used by everything to which you can output data to and we have the abstract <strong>Stream class<\/strong> which inherits from Print and which provides the functioinality to read the data from it. Good examples for Streams are the File and the HardwareSerial class (for the Serial object).<\/p>\n<p>So one good flexible and portable way to <strong>define the output of a TTS<\/strong> functionality is to provide it with an <strong>instance that supports Print<\/strong> so that it can be used to output the generated PCM samples. This supports e.g. the output to<\/p>\n<ul>\n<li>Serial<\/li>\n<li>Files<\/li>\n<li>I2S (if your platform supports it)<\/li>\n<li>and many more<\/li>\n<\/ul>\n<p>My <a href=\"https:\/\/github.com\/pschatzmann\/arduino-audio-tools\">AudioTools library<\/a> is the perfect fit for the second part. You can e.g. output the audio<\/p>\n<ul>\n<li>with the help of PWM<\/li>\n<li>to the internal DAC<\/li>\n<li>to an external DAC<\/li>\n<li>to a Bluetooth Speaker<\/li>\n<li>to Serial has CSV or hex data<\/li>\n<li>to the network using different protocols<\/li>\n<li>and many more<\/li>\n<\/ul>\n<h3>The Talkie Library<\/h3>\n<p>I wanted to extend the <a href=\"https:\/\/github.com\/ArminJo\/Talkie\">quite popular Talkie TTS library<\/a> to provide PCM data, so that we can send it e.g. to a Bluetooth speaker.<\/p>\n<p>Unfortunately I was looking at a big mess of #ifdefs all over the place that were inpossible to untangle. So I decided to go back to the <a href=\"https:\/\/github.com\/going-digital\/Talkie\">original Talkie library<\/a> from <strong>going-digital<\/strong>: Here there was at least a chance to understand what&#8217;s going on, because only one platfrom was supported and the code was quite wells structured. Unfortunately it really took me too much time to figure out how the timer callback and the generation are working together.<\/p>\n<p>After an embarrassingly long time, I finally managed to grok the inner workings and after restructuring the code a bit, I got <strong>my PCM generation finally working<\/strong>.<\/p>\n<p>The generated audio is <strong>16 bits<\/strong> with a <strong>sampling rate of 8000<\/strong> and you can define how many channels you want to generate. E.g for I2S which is a stereo protocol, you can just generate data on the 2 channels.<\/p>\n<p>I decided to <strong>roll my own version of the Library<\/strong> and I called it <a href=\"https:\/\/github.com\/pschatzmann\/TalkiePCM\">TalkiePCM<\/a> to avoid any naming conflicts with the existing libraries. I also added a <strong>CMakeLists.txt<\/strong> to make it usable outside of Arduino.<\/p>\n<h3>An Example Arduino Sketch<\/h3>\n<p>Here is a simple example sketch:<\/p>\n<pre><code>#include \"AudioTools.h\"\n#include \"AudioTools\/AudioLibs\/AudioBoardStream.h\" \n#include \"TalkiePCM.h\" \n#include \"Vocab_US_Large.h\"\n\nconst AudioInfo info(8000, 2, 16);\nAudioBoardStream out(AudioKitEs8388V1);  \/\/ Audio sink\n\/\/CsvOutput&lt;int16_t&gt; out(Serial); \/\/ ouput on screen\nTalkiePCM voice(out, info.channels);\n\nvoid setup() {\n  Serial.begin(115200);\n  AudioLogger::instance().begin(Serial, AudioLogger::Info);\n  \/\/ setup AudioKit\n  auto cfg = out.defaultConfig();\n  cfg.copyFrom(info);\n  out.begin(cfg);\n\n  Serial.println(\"Talking...\");\n}\n\nvoid loop() {\n  voice.say(sp2_DANGER);\n  voice.say(sp2_DANGER);\n  voice.say(sp2_RED);\n  voice.say(sp2_ALERT);\n  voice.say(sp2_MOTOR);\n  voice.say(sp2_IS);\n  voice.say(sp2_ON);\n  voice.say(sp2_FIRE);\n  voice.silence(1000);\n}\n<\/code><\/pre>\n<p>1) We define the <strong>AudioBoardStream<\/strong> out output object which uses the AudioKitEs8388V1 driver, but you can replace this with any supported audio sink class (e.g. I2SStream).<br \/>\n2) We define a <strong>TalkiePCM<\/strong> object giving the above as output and telling it to generate audio in stereo.<br \/>\n3) In the setup we <strong>open<\/strong> the AudioBoardStream;<br \/>\n4) In the loop we just generate the PCM data with the help of the <strong>say() method<\/strong>, which will automatically render to samples to the assinged AudioBoardStream.<\/p>\n<h3>Dependencies<\/h3>\n<p>For this example, you need to have the following libraries installed:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/pschatzmann\/arduino-audio-tools\">arduino-audio-tools<\/a> to output the Audio<\/li>\n<li><a href=\"https:\/\/github.com\/pschatzmann\/arduino-audio-driver\">arduino-audio-driver<\/a> to support the AudioKit<\/li>\n<li><a href=\"https:\/\/github.com\/pschatzmann\/TalkiePCM\">TalkiePCM Library<\/a> to generate the audio from the text<\/li>\n<\/ul>\n<h3>Further Reading<\/h3>\n<p>I am providing quite a <a href=\"https:\/\/www.pschatzmann.ch\/home\/category\/text-to-speech\/\">few other Text to Speach libraries<\/a> that have been convered in the past.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are quite a few popular TTS libraries for Arduino but most of them suffer from the same problem: The TTS function is not properly separated from the output function. Architechture In a properly architected solution we would have a A TTS function which produces platfrom independent PCM data An [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[20,22,35],"tags":[],"class_list":["post-6412","post","type-post","status-publish","format-standard","hentry","category-arduino","category-machine-sound","category-text-to-speech"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>A new Architechture for Talkie: TalkiePCM - Phil Schatzmann<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A new Architechture for Talkie: TalkiePCM - Phil Schatzmann\" \/>\n<meta property=\"og:description\" content=\"There are quite a few popular TTS libraries for Arduino but most of them suffer from the same problem: The TTS function is not properly separated from the output function. Architechture In a properly architected solution we would have a A TTS function which produces platfrom independent PCM data An [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/\" \/>\n<meta property=\"og:site_name\" content=\"Phil Schatzmann\" \/>\n<meta property=\"article:published_time\" content=\"2024-10-21T14:18:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-10-23T07:15:20+00:00\" \/>\n<meta name=\"author\" content=\"pschatzmann\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"pschatzmann\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/\"},\"author\":{\"name\":\"pschatzmann\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#\\\/schema\\\/person\\\/73a53638a4e34e8373405fd737dac9b1\"},\"headline\":\"A new Architechture for Talkie: TalkiePCM\",\"datePublished\":\"2024-10-21T14:18:58+00:00\",\"dateModified\":\"2024-10-23T07:15:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/\"},\"wordCount\":580,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#\\\/schema\\\/person\\\/73a53638a4e34e8373405fd737dac9b1\"},\"articleSection\":[\"Arduino\",\"Machine Sound\",\"Text To Speech\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/\",\"url\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/\",\"name\":\"A new Architechture for Talkie: TalkiePCM - Phil Schatzmann\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#website\"},\"datePublished\":\"2024-10-21T14:18:58+00:00\",\"dateModified\":\"2024-10-23T07:15:20+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2024\\\/10\\\/21\\\/a-new-architechture-for-talkie-talkiepcm\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"A new Architechture for Talkie: TalkiePCM\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#website\",\"url\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/\",\"name\":\"Phil Schatzmann Consulting\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#\\\/schema\\\/person\\\/73a53638a4e34e8373405fd737dac9b1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#\\\/schema\\\/person\\\/73a53638a4e34e8373405fd737dac9b1\",\"name\":\"pschatzmann\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/pschatzmann.png\",\"url\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/pschatzmann.png\",\"contentUrl\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/pschatzmann.png\",\"width\":305,\"height\":305,\"caption\":\"pschatzmann\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/pschatzmann.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"A new Architechture for Talkie: TalkiePCM - Phil Schatzmann","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/","og_locale":"en_US","og_type":"article","og_title":"A new Architechture for Talkie: TalkiePCM - Phil Schatzmann","og_description":"There are quite a few popular TTS libraries for Arduino but most of them suffer from the same problem: The TTS function is not properly separated from the output function. Architechture In a properly architected solution we would have a A TTS function which produces platfrom independent PCM data An [&hellip;]","og_url":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/","og_site_name":"Phil Schatzmann","article_published_time":"2024-10-21T14:18:58+00:00","article_modified_time":"2024-10-23T07:15:20+00:00","author":"pschatzmann","twitter_card":"summary_large_image","twitter_misc":{"Written by":"pschatzmann","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/#article","isPartOf":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/"},"author":{"name":"pschatzmann","@id":"https:\/\/www.pschatzmann.ch\/home\/#\/schema\/person\/73a53638a4e34e8373405fd737dac9b1"},"headline":"A new Architechture for Talkie: TalkiePCM","datePublished":"2024-10-21T14:18:58+00:00","dateModified":"2024-10-23T07:15:20+00:00","mainEntityOfPage":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/"},"wordCount":580,"commentCount":0,"publisher":{"@id":"https:\/\/www.pschatzmann.ch\/home\/#\/schema\/person\/73a53638a4e34e8373405fd737dac9b1"},"articleSection":["Arduino","Machine Sound","Text To Speech"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/","url":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/","name":"A new Architechture for Talkie: TalkiePCM - Phil Schatzmann","isPartOf":{"@id":"https:\/\/www.pschatzmann.ch\/home\/#website"},"datePublished":"2024-10-21T14:18:58+00:00","dateModified":"2024-10-23T07:15:20+00:00","breadcrumb":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.pschatzmann.ch\/home\/2024\/10\/21\/a-new-architechture-for-talkie-talkiepcm\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.pschatzmann.ch\/home\/"},{"@type":"ListItem","position":2,"name":"A new Architechture for Talkie: TalkiePCM"}]},{"@type":"WebSite","@id":"https:\/\/www.pschatzmann.ch\/home\/#website","url":"https:\/\/www.pschatzmann.ch\/home\/","name":"Phil Schatzmann Consulting","description":"","publisher":{"@id":"https:\/\/www.pschatzmann.ch\/home\/#\/schema\/person\/73a53638a4e34e8373405fd737dac9b1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.pschatzmann.ch\/home\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.pschatzmann.ch\/home\/#\/schema\/person\/73a53638a4e34e8373405fd737dac9b1","name":"pschatzmann","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2022\/08\/pschatzmann.png","url":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2022\/08\/pschatzmann.png","contentUrl":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2022\/08\/pschatzmann.png","width":305,"height":305,"caption":"pschatzmann"},"logo":{"@id":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2022\/08\/pschatzmann.png"}}]}},"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/posts\/6412","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/comments?post=6412"}],"version-history":[{"count":25,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/posts\/6412\/revisions"}],"predecessor-version":[{"id":6437,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/posts\/6412\/revisions\/6437"}],"wp:attachment":[{"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/media?parent=6412"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/categories?post=6412"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/tags?post=6412"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}