Welcome back, today were going to start the process of figuring out how to add speech to Mr. Good Bot.

If you need to catch up, here are the other posts in this series so far.

Mr. Good Bot Series

And if you’re just here for the pretty pics, here you go…

The Featured Image:

Daisy Bell Wav Featured Wallpaper
Daisy Bell Wav Featured Wallpaper

Also, you might just want the image inside the audio wave, so… here’s that as well:

Daisy Bell Wallpaper
Daisy Bell Wallpaper

So with the important stuff out of the way, I guess all that is left to do now is figure out how to make Mr. Good Bot talk and decide what he should say first.

Daisy Bell

In 1892 Harry Dacre wrote a popular little ditty called Daisy Bell that was inspired by a trip through customs with a bicycle and a conversation with a friend.

In 1961, an IBM 704 was used to synthesize speech for the first time using a computer.

Prior to that, physical vocoders had been used to create synthetic speech.

A vocoder is an electronic device (these days it’s easy to simulate them with software) that can create a robot voice by using a an input signal (a modulator – typically a human voice but it need not be) and a “carrier” signal (like a pipe organ, colorful noise, sine wave, etc.) to produce an output.

Think 1930’s tele-comm auto-tune as a form of data compression and you’ll be in the ballpark.

Anyway, the song the researchers chose for the 704 unit was Daisy Bell.

Here’s a clip of that:

In 1968 Arthur C. Clarke used Daisy Bell as part of HAL 9000’s death scene in 2001: A Space Odyssey.

You know… if you do a little math:

(H+1)=I (A+1)=B (L+1)=M === HAL === IBM

Not a sponsor but leave a like if you agree they should be! 😛

Anyway, it seems fitting that Mr. Good Bot carry on the ‘Hello World!‘ speech synthesis tradition by singing (monotonically regurgitate) the lyrics to Daisy Bell.

How To Make A Good Bot Talk

It’s always nice to write code that is cross-platform and since I will work on as many systems as possible so that is what we will do today.

I like to target Linux (mainly the Debian branch) as well as Windows OS & Mac OS whenever possible.

Thankfully, PHP (my favorite artificial language) is a cross-platform general purpose programming language and works on all modern operating systems that you and I will be using today.

Since there is no built in TTS (Text to Speech) in PHP (my beloved)…

Here are our options:

  1. Build our own TTS system from scratch.
  2. Find a PHP TTS library.
  3. Use a Built in Speech Synthesis engine that comes with Windows OS or Mac OS , but Linux OS doesn’t have a built in option.
  4. Use a self contained third party solution like eSpeak (not a sponsor) .
  5. Some combination of 3 and 4.

We will almost certainly build our own concatenative TTS system from scratch eventually because I love the idea of preserving Xavier’s little voice so that when I’m old I can still hear his precious baby voice talk but that is a really big multi-post project by itself and not worth the investment of effort for this project… plus while he is very talkative, getting him to consistently say the sentences we need him to say so that we have enough data to extract phonemes to use would be difficult at best right now.

We could try to find a library but that will be hit or miss and will take an investment in time to find and test and since this isn’t a lets learn a library series, that’s out.

I like the idea of using built in native options but Linux doesn’t have a built in option and the other downside to this approach is that this means maintaining two or three different TTS solutions but if we consider the fact that eSpeak sounds like crap and I’m implementing different code either way, I’m forced to conclude that the last option (#5) is probably the best we can do for now.

The Code

Its always nice when somebody has done the hard part already and wrote the code for you!

That’s why I uploaded this code to Rosetta Code and I’ll link the titles to the code on my GitHub.

This code will generate speech for the Daisy Bell lyrics and save it as DaisyBell.wav

TTS_MacAndLinux.php

Use this example if you are on Mac or Linux, note the eSpeak instillation instructions (optional on Mac) in the comments.

<?php


/*
  _      _____ _   _ _    ___   __
 | |    |_   _| \ | | |  | \ \ / /
 | |      | | |  \| | |  | |\ V / 
 | |      | | | . ` | |  | | > <  
 | |____ _| |_| |\  | |__| |/ . \ 
 |______|_____|_| \_|\____//_/ \_\                                  
*/
// Install eSpeak - Run this command in a terminal
/*
 sudo apt-get install eSpeak
*/


/*
  __  __          _____ 
 |  \/  |   /\   / ____|
 | \  / |  /  \ | |     
 | |\/| | / /\ \| |     
 | |  | |/ ____ \ |____ 
 |_|  |_/_/    \_\_____|
*/
// Mac has it's own Speech Synthesis system
// accessible via the "say" command.
// To use eSpeak on a Mac, change this variable to true.
$mac_use_espeak = false;

// To use eSpeak on a Mac you need to install
// Homebrew Package Manager & eSpeak 
// Run these commands in a terminal:
/* 

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

brew install espeak

*/

$voice = "espeak";
$statement = "There is a flower within my heart, Daisy, Daisy!
Planted one day by a glancing dart,
Planted by Daisy Bell!
Whether she loves me or loves me not,
Sometimes it's hard to tell;
Yet I am longing to share the lot
Of beautiful Daisy Bell!

Daisy, Daisy,
Give me your answer, do!
I'm half crazy,
All for the love of you!
It won't be a stylish marriage,
I can't afford a carriage,
But you'll look sweet on the seat
Of a bicycle built for two!

We will go tandem as man and wife, Daisy, Daisy!
Ped'ling away down the road of life, I and my Daisy Bell!
When the road's dark we can both despise Po'leaseman and lamps as well;
There are bright lights in the dazzling eyes Of beautiful Daisy Bell!

Daisy, Daisy,
Give me your answer, do!
I'm half crazy,
All for the love of you!
It won't be a stylish marriage,
I can't afford a carriage,
But you'll look sweet on the seat
Of a bicycle built for two!

I will stand by you in wheel or woe, Daisy, Daisy!
You'll be the bell which I'll ring you know! Sweet little Daisy Bell!
You'll take the lead in each trip we take, Then if I don't do well;
I will permit you to use the brake, My beautiful Daisy Bell!";

$save_file_args = '-w DaisyBell.wav'; // eSpeak args

// Ask PHP what OS it was compiled for, 
// CAPITALIZE it and truncate to the first 3 chars.
$OS = strtoupper(substr(PHP_OS, 0, 3));

// If this is Darwin (MacOS) AND we don't want eSpeak
elseif($OS === 'DAR' && $mac_use_espeak == false) { 
    $voice = "say -v 'Victoria'";
    $save_file_args = '-o DaisyBell.wav'; // say args
}

// Say It
exec("$voice '$statement'");

// Save it to a File
exec("$voice '$statement' $save_file_args");
TTS_Windows.php

The Windows example uses it’s own speech synthesis system called SAPI that is accessible as a COM object.

<?php

// List available SAPI voices
// 0 = Microsoft David Desktop - English (United States)
// 1 = Microsoft Zira Desktop - English (United States)
// ... If you have additional voices installed
function ListSAPIVoices(&$voice){
	foreach($voice->GetVoices as $v){
		echo $v->GetDescription . PHP_EOL;
	}
}

$filename = "DaisyBell.wav";

// https://en.wikipedia.org/wiki/Daisy_Bell#Computing_and_technology
// "In 1961, an IBM 704 at Bell Labs was programmed to sing "Daisy Bell"-
// in the earliest demonstration of computer speech synthesis."
$statement = "There is a flower within my heart, Daisy, Daisy!
Planted one day by a glancing dart,
Planted by Daisy Bell!
Whether she loves me or loves me not,
Sometimes it's hard to tell;
Yet I am longing to share the lot
Of beautiful Daisy Bell!

Daisy, Daisy,
Give me your answer, do!
I'm half crazy,
All for the love of you!
It won't be a stylish marriage,
I can't afford a carriage,
But you'll look sweet on the seat
Of a bicycle built for two!

We will go tandem as man and wife, Daisy, Daisy!
Ped'ling away down the road of life, I and my Daisy Bell!
When the road's dark we can both despise Po'leaseman and lamps as well;
There are bright lights in the dazzling eyes Of beautiful Daisy Bell!

Daisy, Daisy,
Give me your answer, do!
I'm half crazy,
All for the love of you!
It won't be a stylish marriage,
I can't afford a carriage,
But you'll look sweet on the seat
Of a bicycle built for two!

I will stand by you in wheel or woe, Daisy, Daisy!
You'll be the bell which I'll ring you know! Sweet little Daisy Bell!
You'll take the lead in each trip we take, Then if I don't do well;
I will permit you to use the brake, My beautiful Daisy Bell!";

// COM (Component Object Model) objects
// https://www.php.net/manual/en/book.com.php
$voice = new COM("SAPI.SpVoice");
$voice_file_stream = new COM("SAPI.SpVoice");
$file_stream = new COM("SAPI.SpFileStream");


// Change $voice to Zira
$voice->Voice = $voice->GetVoices()->Item(1);

// Change $voice_file_stream to David
$voice_file_stream->Voice = $voice_file_stream->GetVoices()->Item(0);

// Have voices announce themselves
//$voice->Speak($voice->Voice->GetDescription); // (Zira)
//$voice_file_stream->Speak($voice_file_stream->Voice->GetDescription); // (David)


/*
Select Stream Quality:

11kHz 8Bit Mono = 8
11kHz 8Bit Stereo = 9
11kHz 16Bit Mono = 10
11kHz 16Bit Stereo = 11
...
16kHz 8Bit Mono = 16
16kHz 8Bit Stereo = 17
16kHz 16Bit Mono = 18;
16kHz 16Bit Stereo = 19
...
32kHz 8Bit Mono = 28
32kHz 8Bit Stereo = 29
32kHz 16Bit Mono = 30
32kHz 16Bit Stereo = 31
...
*/
// Set stream quality
$file_stream->Format->Type = 17; // 16kHz 8Bit Stereo

/*
Select Speech StreamFile Mode:
Read = 0
ReadWrite = 1
Create = 2
CreateForWrite = 3
*/
$mode = 3;


// Have $voice (Zira) announce beginning file stream
$voice->Speak('Opening audio file stream');

// Output TTS to File
$file_stream->Open($filename, $mode); // Open stream and create file
$voice_file_stream->AudioOutputStream = $file_stream; // Begin streaming TTS
// Have $voice_file_stream (David) speak $statement
$voice_file_stream->Speak($statement); 
$file_stream->Close; // Close stream

// Have $voice (Zira) announce file stream completion
$voice->Speak('File stream complete');

 

GitHub

All of Mr. Good Bot’s code is available for free on my GitHub.


Reader, reader,
Give me your answer, do!
I’m half crazy,
All for the code and you!
It won’t be a stylish blog,
But you’ll enjoy the dialogue,
The bots are sweet on this neat,
website built for you!

If your name is Daisy or you just like my content, consider supporting me on Patreon for as little as $1 a month. 🙂

But, if all you can do is like, share, comment and subscribe… well that’s cool too!

Much Love,

~Joy