Control: We must learn to control
Master Yoda (movie Star Wars) once said: "The key is control." The story-book is read in a word, and I'm going to add two buttons to it so that we can adjust the pitch and speed of speech synthesis in real time.
Still RWTPAGEVIEWCONTROLLER.M, declare the following properties after the Nextspeechindex property:
@property (nonatomic, assign) float currentpitchmultiplier; @property (nonatomic, assign) float currentrate; |
After the Gotopreviouspage: method, add the following method:
- (void)lowerpitch { if (self.currentpitchmultiplier > 0.5f) { Self.currentpitchmultiplier = MAX(self.currentpitchmultiplier * 0.8f, 0.5f) ; } } - (void)raisepitch { if (self.currentpitchmultiplier < 2.0f) { Self.currentpitchmultiplier = MIN(self.currentpitchmultiplier * 1.2f, 2.0f) ; } } - (void)lowerrate { if (self.currentrate > Avspeechutteranceminimumspeechrate) { Self.currentrate = MAX(self.currentrate * 0.8f, avspeechutteranceminimumspeechrate ); } } - (void)raiserate { if (self.currentrate < avspeechutterancemaximumspeechrate) { Self.currentrate = MIN(self.currentrate * 1.2f, avspeechutterancemaximumspeechrate ); } } -(void) speakagain { if (self.nextspeechindex = = [[self currentpage]. Utterances Count]) { Self.nextspeechindex = 0; [self speaknextutterance]; } } |
These methods are connected to the buttons on the Voice Control Panel.
- Lowerpitch: And Raisepitch: Methods are used to reduce and increase pitch, each time decreasing or increasing by 20% on the original basis, but the value is limited to (0.5-2.0).
- Lowerrate: And the Raiserate method is used to reduce and increase the spoken speech speed, each time on the original basis of +/-20%, the overall range is limited to avspeechutteranceminimumspeechrate and Between the avspeechutterancemaximumspeechrate.
- Speakagain: Resets the index value of the current statement and displays the corresponding text content again.
Create a button, and then add the following methods after the Raiserate method:
-(void) addspeechcontrolwithframe: (cgrect) frame title :(nsstring *) title Action:(SEL) selector { UIButton *Controlbutton = [UIButton buttonwithtype:uibuttontyperoundedrect ]; Controlbutton.frame = frame; Controlbutton.backgroundcolor = [uicolor colorwithwhite:0.9f Alpha:1.0f] ; [Controlbutton settitle:title forstate:uicontrolstatenormal]; [Controlbutton addTarget:Self Action:selector forcontrolevents:uicontroleventtouchupinside]; [self.view addsubview:Controlbutton]; } - (void)addspeechcontrols { [self addspeechcontrolwithframe:cgrectmake, 485, - ) Title:@"Lower Pitch" Action:@selector(lowerpitch)]; [self addspeechcontrolwithframe:cgrectmake(222, 485, - ) Title:@"Raise Pitch" Action:@selector(raisepitch)]; [self addspeechcontrolwithframe:cgrectmake(422, 485, - ) Title:@"Lower rate" Action:@selector(lowerrate)]; [self addspeechcontrolwithframe:cgrectmake(592, 485, - ) Title:@"Raise rate" Action:@selector(raiserate)]; [self addspeechcontrolwithframe:cgrectmake(506, 555, - ) Title:@"Speak Again" Action:@selector(speakagain)]; } |
Addspeechcontrolwithframe: The method is a convenient way to add a button to a view and connect it to the appropriate method so that you can adjust the voice by using a button.
Note: You can also create buttons in Main.storyboard and bind their action to Rwtpageviewcontroller. This makes it easier and more efficient.
Before Viewdidload's [self startspeaking] method, add:
//1 Self.currentpitchmultiplier = 1.0f; Self.currentrate = avspeechutterancedefaultspeechrate; //2 [self addspeechcontrols]; |
Note The default speech properties are set at "1", and the Voice control button is added at the comment "2".
Finally, modify the Speaknextutterance method:
- (void)speaknextutterance { if (self.nextspeechindex < [[self currentpage]. Utterances Count]) { Avspeechutterance *utterance = [[self currentpage]. Utterances Objectatindex :self.nextspeechindex]; Self.nextspeechindex + = 1; //1 Utterance.pitchmultiplier = self.currentpitchmultiplier; //2 Utterance.rate = self.currentrate; [self.synthesizer speakutterance:utterance]; } } |
If you click the Lower/raise button, the newly set value will be applied in the next sentence read aloud.
Compile and run. As shown in the following:
Touch or click on these buttons, then note the changes in pronunciation. Yoda is really powerful, even if you are not a Jedi can become a master (Avspeechsynthesizer).
End
The complete project code can be downloaded here.
Hopefully this article will be the motivation to inspire you to develop your own audio books. If you want to know more about how to tune synthetic speech, see below:
Best Audio Book Whirlysquirrelly.plist contest
Note: Please try to further tune the whirlysquirrelly.plist and upload it to the forum or message in this article. We will review the winners and compliment them in the comments.
Allow users to select books
Description: Add a "Choose book" button and display an optional list of books in Uipopovercontroller. When the user selects a book, resets the book object in Rwtpageviewcontroller and displays the new books.
Download books from the Web
Description: Store books in plist format on a Web server or provide services similar to AWS S3 or Heroku. The server first provides a list of URLs, lists all the books, and then provides a service to download a book. In the previous feature, add a link to the book.
Read the word highlighting
Tip: Use the methods in the Avspeechsynthesizerdelegate delegate
In the Speechsynthesizer:didstartspeechutterance: method, highlight the specified utterance.
In the Speechsynthesizer:didfinishspeechutterance: method, highlight the highlighted utterance. You can use the Pagetextlable Attributedtext property to set different background colors and font properties with nsattributedstring to achieve the highlight effect.
Show title on the first page
Addthe ability to Display a Title Page before all other Pages
Description: Add an additional viewcontroller before Rwtpageviewcontroller and set the Main.storyboard property to have the new Viewcontroller enabled. Manage two viewcontroller with one uinavigationcontroller. To do this, you can modify the design of the page class and divide it into an audible page and a silent page, and then modify the Rwtpageviewcontroller so that it can handle the two different page types.