Skip to content

Commit

Permalink
Added notes and solution for Project 23 - Speech Synthesis Voiceinato…
Browse files Browse the repository at this point in the history
…r 5000
  • Loading branch information
lisaychuang committed Jun 10, 2018
1 parent 06b0973 commit b69ec49
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 11 deletions.
98 changes: 88 additions & 10 deletions 23 - Speech Synthesis/index-projectnotes.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,110 @@
<div class="voiceinator">

<h1>The Voiceinator 5000</h1>


<!-- drop down options of voices avail -->
<select name="voice" id="voices">
<option value="">Select A Voice</option>
</select>

<!-- Scroll bar to change rate -->
<label for="rate">Rate:</label>
<input name="rate" type="range" min="0" max="3" value="1" step="0.1">

<!-- Scroll bar to change pitch -->
<label for="pitch">Pitch:</label>

<input name="pitch" type="range" min="0" max="2" step="0.1">

<!-- Text area to enter text, buttons-->
<textarea name="text">Hello! I love JavaScript 👍</textarea>
<button id="stop">Stop!</button>
<button id="speak">Speak</button>

<!-- STRETCH GOAL: added pause & resume features -->
<button id="pause">Pause</button>
<button id="resume">Resume</button>

</div>

<script>
const msg = new SpeechSynthesisUtterance();
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');
const options = document.querySelectorAll('[type="range"], [name="text"]');
const speakButton = document.querySelector('#speak');
const stopButton = document.querySelector('#stop');


const msg = new SpeechSynthesisUtterance();

// array to contain voice options
let voices = [];
const voicesDropdown = document.querySelector('[name="voice"]');

// selection options
const options = document.querySelectorAll('[type="range"], [name="text"]');
const speakButton = document.querySelector('#speak');
const stopButton = document.querySelector('#stop');
const pauseButton = document.querySelector('#pause');
const resumeButton = document.querySelector('#resume');

// get textarea value
msg.text = document.querySelector('[name="text"]').value; //OR msg.text = document.querySelector('textarea').value;


// populate voice options in drop-down menu
function populateVoices(){
voices = speechSynthesis.getVoices(); // get all voice options, store in array

const voiceOptions = voices
.filter(voice => voice.lang.includes('en')) // add filter for Eng voices
.map(voice => `<option value ="${voice.name}">${voice.name} (${voice.lang})</option>`)
.join('');

voicesDropdown.innerHTML = voiceOptions;
};

// stop speech, or restart speech when user selected a different voice
function toggle(startOver = true){
speechSynthesis.cancel();

if (startOver) {
speechSynthesis.speak(msg);
};
};

// set voice based on selection in drop-down menu
function setVoice(){
// get speechSynthesis voice object based on selected option
msg.voice = voices.find(voice => voice.name === this.value);

toggle(); // restart speech every time a new voice is selected
};

// set Option value everytime user change an input
function setOption(){
console.log(`Setting ${this.name} to ${this.value}`);
msg[this.name] = this.value;
toggle();
};

// event handlers
speechSynthesis.addEventListener('voiceschanged', populateVoices);
voicesDropdown.addEventListener('change', setVoice);

options.forEach(option => option.addEventListener('change', setOption));

speakButton.addEventListener('click', toggle);
stopButton.addEventListener('click', () => toggle(false)); // inline function

// use .bind() to pass argument to a function
// stopButton.addEventListener('click', toggle.bind(null, false));

// STRETCH GOAL
// added pause & resume button features

function pause(){
speechSynthesis.pause();
}

function resume(){
speechSynthesis.resume();
}
pauseButton.addEventListener('click', pause);
resumeButton.addEventListener('click', resume);

</script>

</body>
Expand Down
4 changes: 4 additions & 0 deletions 23 - Speech Synthesis/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,7 @@ input[type="select"] {
.voiceinator button:nth-of-type(1) {
margin-right: 2%;
}

.voiceinator button:nth-of-type(3) {
margin-right: 2%;
}
65 changes: 64 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -1019,4 +1019,67 @@ The returned value is a `DOMRect` object which is the union of the rectangles re

The result is the smallest rectangle which contains the entire element, with read-only `left, top, right, bottom, x, y, width`, and `height` properties describing the overall border-box in pixels.

Properties other than `width` and `height` are relative to the top-left of the viewport.
Properties other than `width` and `height` are relative to the top-left of the viewport.

## Project 23: Speech Synthesis

In project 20, we learned to use the `SpeechRecognition` interface. In this project, we learned about the `SpeechSynthesisUtterance` interface to add speech service to our web app.

### [SpeechSynthesisUtterance interface](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance)
The `SpeechSynthesisUtterance` interface of the Web Speech API represents a speech request. It contains the content the speech service should read and information about how to read it (e.g. language, pitch and volume.)

#### [SpeechSynthesisUtterance() constructor](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance/SpeechSynthesisUtterance)
The constructor returns a new `SpeechSynthesisUtterance` object instance, which has various properties that can get and set the language, pitch, speed, voice, volume of the utterance (or speech) to be spoken.

In this project, we defined these properties:

- `SpeechSynthesisUtterance.text`: Gets and sets the text that will be synthesised when the utterance is spoken.
- `SpeechSynthesisUtterance.pitch`: Gets and sets the pitch at which the utterance will be spoken at.
- `SpeechSynthesisUtterance.rate`: Gets and sets the rate at which the utterance will be spoken at.
- `SpeechSynthesisUtterance.voice`: Gets and sets the voice that will be used to speak the utterance.


### [SpeechSynthesis interface](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis)

The `SpeechSynthesis` interface of the Web Speech API is the controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech etc.

In this project, we used these methods:

- `SpeechSynthesis.getVoices()`: Returns a list of `SpeechSynthesisVoice` objects representing all the available voices on the current device. (e.g. English, French)

This list is retrieved with an event handler, `SpeechSynthesis.onvoiceschanged` which fires when the list of `SpeechSynthesisVoice` objects that would be returned by the SpeechSynthesis.getVoices() method has changed.

- `SpeechSynthesis.speak()`: Adds an `utterance` to the utterance queue; it will be spoken when any other utterances queued before it have been spoken.
- `SpeechSynthesis.cancel()`: Removes all utterances from the utterance queue.


### [Function.prototype.bind()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)
The `bind()` method creates a new function that, when called, has its `this` keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

Syntax: `function.bind(thisArg[, arg1[, arg2[, ...]]])`

`thisArg`: The value to be passed as the `this` parameter to the target function when the bound function is called.
`arg1, arg2, ...`:
These arguments (if any) follow the provided `this` value, and are then inserted at the start of the arguments passed to the target function, followed by the arguments passed to the bound function, whenever the bound function is called.

MDN Guides provide two great examples showing how to create a `bound function` and a `partially applied function`.

In this project, we used the `.bind()` method in the `stopButton` event handler to create a partially applied function:

```js
function toggle(startOver = true){
speechSynthesis.cancel();

if (startOver) {
speechSynthesis.speak(msg);
};
}

stopButton.addEventListener('click', toggle.bind(null, false));
```

When the `stopButton` is clicked, the event handler will execute the `toggle()` function with an initial value `false`

i.e. `toggle(false)` which will call `speechSynthesis.cancel()` method to stop speech utterance.


0 comments on commit b69ec49

Please sign in to comment.