English text to speech on a PIC microcontroller

4.00 avg. rating (84% score) - 1 vote

I have always been a fan of the TTS256 – a tiny but great English text-to-speech IC based on a 8-bit microprocessor for embedded voice applications. Unfortunately, the TTS256 has been out of production for a long time and despite better technology being developed over the years, chip manufacturers do not seem to be interested in developing a similar or better text to speech IC, leaving the average electronics hobbyists searching eBay for second-hand TTS256 ICs, often listed at unreasonable price.

Nowadays, SpeakJet by Sparkfun and RoboVoice by Speechchips are among the few available text-to-speech modules for embedded projects. Both are priced at 20-30 USD and have pinout and interface commands similar to the TTS256. Although these speech modules come in handy, their price range seems a bit high for many projects. Hence, I decided to search for free alternatives.

Syntho and PICTalker

There are several open source text-to-speech projects for 8-bit microcontrollers such as Syntho and PICTalker, built for the PIC16F616 and PIC16F628 respectively. In both projects, one or more EEPROMs are used to store the phoneme database. The EEPROM size is around 64K for the PICTalker project and is made smaller by using innovative compression techniques in the Syntho project. Both projects require phonemes (and not English text) to be sent before they can be pronounced. This is due to the lack of a rule database to convert text to phonemes, presumably due to the limited amount of memory available. These solutions are somewhat closer to the SPO256, which requires phonemes as input, rather than the TTS256, which accepts English text.

If you don’t know what phonemes are, read this on Wikipedia. They are simply the phonetic representations of a word’s pronunciation. There are approximately 44 phonemes in English to represent both vowels and consonants.

Below is a voice sample of the Syntho project, which is trying to say “I am a really cheap computer”:

As expected, the voice sounds too mechanical and can hardly be understood.

Arduino TTS library

Next I came across another TTS library made for the Arduino and decided to give it a quick try to test the speech quality. As I do not have an Arduino board available, I ported them to a Visual Studio 2012 C++ application which accepts English text as input and saves the resulting speech as a wave file. The ported code can be downloaded here. If you intend to use this code, take note that it only writes the wave data for the generated speech and ignores the wave file header. You will probably need a professional sound editor software such as Goldwave to play and examine the generated file. This is because calculating the exact total duration of the generated speech (required for creating the wave file header) is complicated and there is no need for me to attempt that since the code is only for testing.

This is the generated voice sample. It is trying to say “Hello Master, how are you doing? I am fine, thank you.”:

Although the quality is obviously better than the PICTalker, it still sounds robotic and difficult to understand.

SAM (Software Automatic Mouth) project

My next attempt is to see if the same can be done on a PIC, with better speech quality. By chance, I came across SAM (Software Automatic Mouth), a tiny (less than 39KB) text-to-speech C program. The project website contains a tool to generate a demo voice from the text entered.

After getting the Windows source code to compile and run without issues in Visual Studio (download the project here), I decided to port the code to the PIC24FJ64GA002, which is surprisingly rather straightforward. The only challenge was to get all the 32-bit data types in the original source code ported properly to the 16-bit architecture of the PIC24 micro-controller, and to get the rule and phoneme database fit nicely into the PIC24FJ64GA002 available memory. Fortunately, the entire project when compiled uses just around 50% of the total program and data memory on the PIC24FJ64GA002, leaving available space for other codes.

You may be able to fit the project into the smaller PIC24FJ32GA002 by changing the project build options to use the large memory model during compilation:

However, in my experiment, the code compiled but ran erratically when using large memory model, perhaps due to pointer behavior differences. It is therefore better to compile with the default settings and use the PIC24FJ64GA002 (or one with more memory) to save the trouble and have more code space for other purposes.

The following is a recording of the generated speech for the sentence “This is SAM text to speech. I am so small that I will work also on embedded computers”, when running on the PIC24 using PWM for audio output.

Below is a longer demo speech. Can you understand what it is trying to say?

As can be seen, the quality of the generated speech is much better – less mechanical, clearer pronunciation and easier to understand. Although the voice still sounds robotic and there are some mispronounced words, the overall quality should be good enough to be used in embedded projects, as a free alternative to current commercial text to speech solutions.

With some pitch adjustments, the PIC24 can also sing “The Star-Spangled Banner”, the national anthem of the United States of America:

The complete ported code, as a MPLAB 8 PIC24FJ64GA002 project, can be downloaded here. The project also contains example codes for the SYN6288, a Chinese text-to-speech module.

UPDATE (July 2019)

After almost five years, a quick Google search revealed that the above code has inspired many other similar projects, for example this and this. In both links the authors have ported the code to PIC32 and improved the algorithm to make the audio quality better. A post on the second link also pointed out that my ported PIC24 code contains an error in ReciterTabs.h causing the code to ignore question marks. To fix the bug, edit ReciterTabs.h line 210,  replace 174 with 191 and the code will correctly boost the tone when a question mark is detected. This bug does not exist on the original SAM so I believe the wrong array value could have been added when I ported ReciterTabs.h to PIC24. If I recalled correctly, there were some issues reading those values and I could have made the mistake as I altered several values to debug the code.

Amazingly, on the same discussion on The Back Shed, somebody named Frank has added German phonemes making it possible for SAM to speak the language. The audio quality was pretty good during my tests and I planned to write another article about the PIC32 German port soon. In the mean time, you can download the ported source codes and binaries here.



See also

SYN6288 Chinese Speech Synthesis Module  
LD3320 Chinese Speech Recognition and MP3 Player Module

4.00 avg. rating (84% score) - 1 vote


A tough developer who likes to work on just about anything, from software development to electronics, and share his knowledge with the rest of the world.

5 thoughts on “English text to speech on a PIC microcontroller

  • April 30, 2015 at 2:17 pm

    Thanx a ton for such a great help with the sam project.
    Can u help us with providing hardware schematic of the project please?
    I am also doing same kind of project so it would be great help if u provide us the requested.

  • April 30, 2015 at 11:45 pm

    The output of the text to speech is using PWM at pin RB5. If you have a crystal earpiece, you can just connect pin RB5 directly to the earpiece and you should hear SAM speaking. Otherwise you will need an amplifier to amplify the signal output before you can connect it to your 8-ohm speaker. For simplicity, you can try to use an LM386 to amplify the output, refer to the circuit below http://web.mit.edu/6.s28/www/schematics/lm386.htm

    Because the output is in PWM (Pulse Width Modulation), it may not sound good on an 8-ohm speaker since it’s square wave. To make the audio better you will need to use an RC circuit to make the output signal look more like sine wave. You can use the circuit in step 2 (RC filter) of this article http://www.instructables.com/id/Arduino-RC-Circuit-PWM-to-analog-DC/ . Feed the output at pin RB5 to this filter, then feed the filter output to the LM386 amplifier. The audio quality should sound good enough for most purposes.

    Alternatively, you can also try other single transistor audio amplifier circuit or a single-chip solution such as PAM8403 5V Mini Class-D digital Amplifier that can be purchased for a cheap price from eBay. With the PAM8403, you can just feed the input audio to the amplifier and connect the speaker to the module directly without any external components.

    Hope you will get this working. Let me know if you have any other questions

  • June 25, 2015 at 11:18 pm

    Muchas gracias!!!!!!. Me compre hace unos dias un PIC24F. Voy a poder probarlo.

  • October 13, 2021 at 4:22 pm

    I am Frank from The Back Shed. After a long time I googled for TTS again, I saw that you have found my adaptation on The Back Shed. Nice that you like it! Without your preparatory work and without Peter of The Back Shed this would not have been possible – at this point many thanks for that!
    I simply assigned the most similar sounding phonemes to the German letters for the German conversion. Fortunately, the German language is structured in such a way that most words are also spoken as they are written. This makes things a lot easier!
    Most of the words are understandable right away, for the others it is usually enough to write the word “wrong” so that it is pronounced correctly…
    Thanks also for making the code available for download – so it can’t get lost so easily on the web! :-)

    Many greetings


  • December 17, 2022 at 8:04 pm

    Man, you can use pwm to simthetyze the sound. …also, some pic have dac 8 bit inside. It is not 5star, but the sound is quite good…

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>