A rudimentary voice synthesiser in less than 1kB of code.

Similar projects worth following
This is a very old project of mine, resurrected from the compost drawer where it has been rotting for the last 22 years (sigh)!
Originally it was based on an 18-pin PIC16CR56 (!) and used 24 resistors to create an (R-2R) poor man DAC. It would "say" the (Italian) world "SISTEMA" ( don't ask, long story) using less than 1K byte of code (582 x 12-bit PIC words = *12/8 = 873 bytes)
I intend to port it to a (bit) more modern microcontroller model, possibly in a smaller package and see what/how I can improve in the process...
Should be fun!

I found a clear box (see picture) with the sticker "SPIC". This makes me think that the original project name must have been a pun on the PIC microcontroller name. Honestly I cannot remember it anymore though. In my "archives" there is no trace of a SPIC folder but I could only find a "PICSPEAK" folder, hence the name I used on here (

Unfortunately the PIC16CR56 is missing (see empty socket) but I am not sure I want/need to find an original sample. (I would then need to find a tool to program it, and those where NOT the days of "in circuit", "serial" programming...

My plan is to rescue the code (ASM) and port it to a 6-pin SOT 23 microcontroller (PIC10F322). See picture of a PIC10F3xx eval board I'd like to use!

  • 1 × PIC10F322 Microprocessors, Microcontrollers, DSPs / ARM, RISC-Based Microcontrollers
  • 2 × 1.5V battery
  • 1 × Minimal Audio Amplifier or just a pair of headphones, PIC I/Os are so forgiving ...

  • Reality Check

    lucio01/05/2017 at 08:57 0 comments

    Uhm, fiddling with the audio samples and recycling one single vowel to produce all the required one by simply freq. shifting with the NCO was an interesting experiment but it definitely fizzled. As in, it just did not work!

    I am also disappointed by the results of my (lazy) attempt to re-target to the word "Hackaday". I should either take it more seriously and re-sample new vowels/consonants that are more appropriate for the target word or stick to the original "message". After all there is a whole lot of nostalgia that goes with that (albeit that would apply only for me :) Will revert the "segments" table shortly.

    Minor hw update as well. I have separated the PIC10F board from the proto area (that I immediately re-used for another project) and re-soldered the pushbutton (SW1) notably missing in the early pictures... Also added a semi-proper connector for my scope probe and the audio amplifier (just headphones actually).

    Lessons learned:

    1 - Be humble. As rudimentary as my audio sample collection/manipulation was 20+ years ago, it was nonetheless somewhat optimal for the target.

    2 - NCO peripheral definitely useful for future little tricks. I will explore possibility to freq. shift in WAV-1K project when playing back from an SD card...

  • Numerically Controlled Oscillator

    lucio12/11/2016 at 22:10 0 comments

    So I did try to use the NCO (Numerically Controlled Oscillator) to generate a variable time base for each vowel and it kind of worked. It actually turned out to be easier than expected.

    The idea worked like this:

    1. I kept the PWM working on TMR2 with a fixed frequency of 32kHz.
    2. I modified the main loop to wait on the NCO interrupt instead of the TMR2 postscaler.
    3. I assigned an initial NCO "increment" (524) to obtain the standard 8kHz sample rate.

    I run a test to verify that this way I would get the same output as before (when using the TMR2 interrupt). it did!
    (NOTE: increment = Fout / (Fosc / 2^20) = 8000 / (16MHz/1MB) = 524)


    1. I removed the tables for the vowels 'e' and 'i' and replaced them in the scheduler with 'a'.
    2. I added for each 'part' in the schedule a setting for the NCO increment leaving the value to 524 ( the constant EIGHTK) for all non vowels.
    3. I scaled the value of INC proportionally to the length of each of the vowels tables. (E = 645, I = 870)

    While debugging the new code I found out a bug in the "silence" table (the signature was supposed to be changed to 0xff, but I had forgotten to update it).

    I created a new branch of the project on Github (NCO) and later went back and fixed the "silence bug" in the "master" too...

  • Back to the Future

    lucio12/09/2016 at 09:54 0 comments

    So I was looking at the samples (tables) forming the vowels "a", "e", "i" used in the original code and just figured out that they all look very (suspiciously) similar. The length (period) being the most (obvious) distinguishing element. Clearly I had no good tools at the time to "clean up" or simply to handle the audio signal. The effective resolution appears to be awfully small 4-5 bit?

    I am amazed in fact in re-discovering the Turbo Pascal code I used back then to "edit" the WAV files and extract semi-automatically those tables. (You will find the source in the "archive" folder...). Does anybody have a copy of the might Borland Turbo Pascal that would run on my Mac? I am almost afraid to ask, somebody actually might!

    Today I am sure I would have used an OSS tool such as "Audacity" or a 5 lines script in Python (import wave) or ... simply Excel !!!

    (Libre Office I meant!)

  • First Port to the PIC10

    lucio12/07/2016 at 10:54 0 comments

    I have completed the port to the PIC10 and the little (6-pin) critter speaks!

    Very interesting exercise indeed. First of all I had to refresh my PIC assembly. I was amazed how much rust had accumulated in only a couple of years (or is it more) of "only" C programming. The original code was written for 12-bit "baseline" PICs, the old C5X series, and that used to come with a whole lot of restrictions and complications that I had almost completely forgotten about. For example, subroutines could only be called in the lower half of the program space. Since the only way to implement a lookup table in those days was to use the "idiosyncratic" RETLW opcode... tables themselves were restricted or rather we used to jump through hoops!

    Now the PIC10F3xx, is a "mid-range" PIC, meaning the instructions are 14-bit wide which allowed me to move things around a bit. I now for a fact that the code does fit now!

    The PIC10F32x also comes with a convenient PWM, and that can be clocked fast enough (using only the internal oscillator) to produce an audio D/A, so all I need now is a single output pin.

    Most importantly, I programmed the code on the little PIC10F demo board (see picture) and connected (poorly) a little audio amplifier: it does speak, kind of ...

    Definitely not happy with the quality of the sound, I am going to investigate how the ... I did come up with those samples back then. What was I thinking?

    Also I see a few possible directions (branches?) this project could take from here:

    1- Investigate use of the NCO (frequency synthesiser) peripheral (instead of the fixed PWM) to frequency shift a single sample waveform and produce the multiple vowels needed. I need to think this one through...

    2- Evaluate replacing the RETLW tables with proper NVM access. The PIC10F3' Flash read/write module allows full access to the program flash word. That would give me 14-bit of data for each word instead of just 8. I could pack double the number of samples...

    3- I could get adventurous and try to change the "spoken" word into something more appropriate for the contest ("one k", or "Hackaday"?)

View all 4 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates