TweetFollow Us on Twitter

Feb 00 Getting Started

Volume Number: 16 (2000)
Issue Number: 2
Column Tag: Getting Started

Speech Channels

by Dan Parks Sydow

Getting a speech-capable program ready for the use of different voices

In last month's Getting Started article we started in on the topic of speech in Macintosh programs. There you saw how your program can verify that the user's Mac is able to output speech, and you saw how your program can use the SpeakString() function to speak the text of one string. That was a good start, but if your program is to make good use of speech there are a couple of other speech-related issues to cover. You'll want your program to have the ability to speak more than a single string (without having to repeatedly call SpeakString()). This month we see how that can be done. You'll also want to give your program the power to speak in different voices. In last month's code we relied on the default voice - whatever voice is currently set for use on the user's machine. But the user has a wealth of different voices stored on his or her Mac - and your program can make use of any one of them! This month we'll see how to make use of speech channels. An application-allocated speech channel is a prerequisite for speaking in a different voice - so armed with this new speech channel information you'll be ready for next month's Getting Started article where we wrap up the topic of speech by creating an application that speaks in different voices.

Speech Basics Review

It's the Speech Manager - along with a speech synthesizer (that's a part of the Mac system software), the Sound Manager, and a Mac's audio hardware - that makes speech possible. If a Mac program is to speak, it should include the Speech.h universal header file to ensure that the compiler recognizes the speech-related Toolbox functions.

#include	<Speech.h>

Before attempting to speak, your program should verify that the user's machine will be able to output the sound (refer to last month's article if you need an explanation of the following snippet).

OSErr	err;
long		response;
long		mask;

err = Gestalt( gestaltSpeechAttr, &response );
if ( err != noErr )
	DoError( "\pError calling Gestalt" );

mask = 1 << gestaltSpeechMgrPresent;	
if ( response & mask == 0 )
 	DoError( "\pSpeech Manager not present " );

To speak a single string of text, use the SpeakString() function. Pass this function a Pascal-formatted string and SpeakString() turns the characters that make up the string into speech that emits from the user's Mac. Follow a call to SpeakString() with repeated calls to SpeechBusy() to ensure that time is provided for the full text of the string to be spoken.

OSErr	err;

err = SpeakString( "\pThis is a test." );
if ( err != noErr )
	DoError( "\pError attempting to speak a phrase" );   
while ( SpeechBusy() == true )
	;

Speech Channels

Whenever a Mac program speaks, a speech channel is involved. A speech channel is a data structure that holds descriptive information about speech that is to "pass through" that specific channel. The most important property that the channel keeps track of is the voice to use. If you want your program to speak in two different voices (perhaps a conversation between two people is going on), then you'd create two speech channels - each channel specifying a different voice. Each time your program speaks, you'd designate which channel is used, basing the decision on which voice is appropriate for the words that are about to be spoken.

Last month you learned about SpeakString() - the easy-to-use Toolbox function that speaks the text comprising a single string. In last month's article we didn't need to cover speech channels because when a call is made to SpeakString(), the Speech Manager takes care of the allocation of a speech channel. The Speech Manager than uses that channel to speak, and disposes of that same channel when speaking has completed. Because the Speech Manager takes care of all this behind the scenes, SpeakString() is very simple to use. There's a drawback to using SpeakString() though - the programmer lacks control of the speech channel. Because of this, a specific voice can't be selected. Instead, SpeakString() always uses the system default voice. Here you'll see how to create a new speech channel and then use a different Toolbox function - SpeakText() - to specify that this new channel be used when your program speaks.

Use the Toolbox function NewSpeechChannel() to create a new speech channel. This routine allocates memory for a SpeechChannelRecord. This is the data structure that holds information about a speech channel. NewSpeechChannel() finishes by returning to your program a SpeechChannel - a pointer to the new speech channel record.

SpeechChannel	channel;
OSErr					err;

err = NewSpeechChannel( nil, &channel );	

The first NewSpeechChannel() argument is a pointer to a voice specification data structure. As you'll see in next month's Getting Started article, this data structure corresponds to the voice that is to be used for speech generated through this one speech channel. To simply use the system default voice, pass nil as the first argument (as shown here).

The second argument is the address of a SpeechChannel - a data structure that holds the information about a speech channel. After NewSpeechChannel() allocates the speech channel record, this variable references the new record.

The Toolbox should have no problem allocating a new speech channel, but you'll want to prepare for the worst. If NewSpeechChannel() returns an OSErr value other than noErr, you can use some standard error-catching routine like our own DoError(), or you can opt to call the Toolbox function DisposeSpeechChannel() to dispose of the problematic channel yourself. You might also want to set the SpeechChannel variable to nil to indicate to your program that the variable doesn't hold a valid reference to a speech channel.

if ( err != noErr )
{
	err = DisposeSpeechChannel( channel );
	channel = nil;
}

Your primary use of a speech channel will be in calls to the Toolbox function SpeakText(). Unlike SpeakString(), which accepts just a string of text to speak, SpeakText() accepts a speech channel and a buffer of text to speak. Here's a typical call to SpeakText():

OSErr	err;
Str255	str = "\pHere's a test of SpeakText.";

err = SpeakText( channel, (Ptr)(str + 1), str[0] );
if ( err != noErr )
	DoError( "\pError attempting to speak a phrase" );

while ( SpeechBusy() == true ) 
	;

The first SpeakText() argument is a speech channel. Here we aren't making good use of the speech channel - but next month, we will.

The second argument is a pointer to the area of memory that holds the text to speak. In the above example I've used a string to represent the text. Your program could also append strings together in a buffer, or read text from an external file to a buffer. A variable of type Str255 uses its first byte to hold the length (in bytes) of the string, and the remaining bytes to hold the characters that make up the string. If we just used str as the second argument, SpeakText() would attempt to start speaking using the value in the first byte of str - which happens to be a number. By using str + 1, we tell SpeakText() to move to the second byte of str and start speaking from there. Finally, because SpeakText() requires a generic pointer to a buffer, the Str255 variable needs to be typecast to type Ptr. Collectively (Ptr)(str + 1) make up the second argument.

The third SpeakText() argument is the number of bytes that should be used from the buffer. In the case of a Str255 variable, the number of bytes making up the string is held in the first byte of the variable. So the first element (byte [0]) in the Str255 variable represents the number of buffer bytes holding characters to speak.

As you did for SpeakString(), end with repeated calls to SpeechBusy() to provide ample time for the Mac to speak the words in the SpeakText() buffer.

SpeechChan

This month's program is SpeechChan. This simple, non-menu-driven program provides a working example of how to create and make use of a sound channel. When run, SpeechChan speaks the phrase "We've successfully opened a speech channel". After speaking those words the program quits.

Creating the SpeechChan Resources

Start by creating a new folder named SpeechChan in your CodeWarrior development folder. Launch ResEdit and create a new resource file named SpeechChan.rsrc. Specify that the SpeechChan folder serve as the resource file's destination. This resource file will hold only two resources. As shown in Figure 1, you'll need just an ALRT and a DITL resource for this project.


Figure 1. The SpeechChan resources.

The resource file will hold one alert resource - ALRT 128. Corresponding to this ALRT is DITL 128. Together these two resources define the program's error-handling alert. If your version of the SpeechChan program doesn't commit any serious errors, then the program won't make use of these resources.

Creating the SpeechChan Project

Create a new project by starting up CodeWarrior and choosing New Project from the File menu. Use the MacOS:C_C++:MacOS Toolbox:MacOS Toolbox Multi-Target project stationary for the new project. Uncheck the Create Folder check box before clicking the OK button. Name the project SpeechChan.mcp, and specify that the project's destination be the existing SpeechChan folder.

Now add the SpeechChan.rsrc resource file to the project. Remove the SillyBalls.rsrc file. The ANSI Libraries folder can stay or go - as is the case for most of our example projects, we aren't making use of any ANSI C libraries, so you can remove them from the project if you wish.

If you plan on making a PowerPC version (or fat version) of the SpeechChan program, be sure to add the SpeechLib library to the PowerPC targets of your project. As mentioned last month, you'll want to choose Add Files from the Project menu and work your way over to this library. You'll find it in the Metrowerks CodeWarrior:MacOS Support:Libraries:MacOS Common folder. If you can't find the library in that folder, use Sherlock to search your hard drive for it. When you add the library to the project CodeWarrior displays a dialog box asking you which targets to add the library to. Check the two PPC targets. In Figure 2 you see how your project will look with the SpeechLib library added to it.


Figure 2. The SpeechChan project.

Now create a new source code window by choosing New from the File menu.. Save the window, giving it the name SpeechChan.c. Choose Add Window from the Project menu to add the new empty file to the project. Remove the SillyBalls.c placeholder file from the project window. At this point you're ready to type in the source code.

If you want to save yourself a little typing, connect to the Internet and visit MacTech's ftp site at ftp://ftp.mactech.com/src/mactech/volume16_2000/16.02.sit. There you'll find the SpeechChan source code file available for downloading.

Walking Through the Source Code

SpeechChan.c starts with the inclusion of the Speech.h file. If you compile the source file and you receive a number of undefined function errors, then you most certainly forgot to include this universal header file.

/********************** includes *********************/

#include	<Speech.h>

After the #include comes a single constant. The constant kALRTResID holds the ID of the ALRT resource used to define the error-handling alert.

/********************* constants *********************/

#define		kALRTResID						128 

Next come the program's function prototypes.

/********************* functions *********************/

void						ToolBoxInit( void );
SpeechChannel	OpenOneSpeechChannel( void );
void						DoError( Str255 errorString );

The main() function of SpeechChan starts with the declaration of several variables. The first three variables, err, response, and mask, are used in the determination of whether speech generation is possible on the user's Mac. The other two variables, str and channel, are used in the generation of speech.

/********************** main *************************/

void		main( void )
{ 
	OSErr	err;
	long		response;
	long		mask;
	Str255	str ="\pWe've successfully opened a speech channel.";
	SpeechChannel	channel;

After the Toolbox is initialized the previously discussed speech-related tests are made:

	ToolBoxInit();

	err = Gestalt( gestaltSpeechAttr, &response );
	if ( err != noErr )
		DoError( "\pError calling Gestalt" );

	mask = 1 << gestaltSpeechMgrPresent;	
	if ( response & mask == 0 )
		DoError( "\pSpeech Manager not present " );

Now we get down to business. First, a speech channel is allocated and a reference to it is saved in local variable channel. Note that this local variable could have been a global variable - the choice is dependent on your programming style. The application-defined function OpenOneSpeechChannel() is described just ahead.

	channel = OpenOneSpeechChannel();

	if ( channel == nil )

		DoError( "\pError opening a speech channel" );

With a valid speech channel, we can make a call to SpeakText(). The arguments here match the ones described in this article's previous SpeakText() example snippet.

	err = SpeakText( channel, (Ptr)(str + 1), str[0] );
	if ( err != noErr )
		DoError( "\pError attempting to speak a phrase" );

	while ( SpeechBusy() == true ) 
		;

When we're finished speaking, we dispose of the speech channel. Unlike a call to SpeakString(), SpeakText() required our efforts in creating the speech channel. We made it, so we need to throw it out.

	err = DisposeSpeechChannel( channel );
	if ( err != noErr )
		DoError( "\pError disposing speech channel" );
}

ToolBoxInit() remains the same as previous versions.

/******************** ToolBoxInit ********************/

void		ToolBoxInit( void )
{
	InitGraf( &qd.thePort );
	InitFonts();
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs( nil );
	InitCursor();
}

OpenOneSpeechChannel() calls NewSpeechChannel() to create a new speech channel. The OpenOneSpeechChannel() routine is called from main(), so that's where the reference to the newly created channel gets returned.

/*************** OpenOneSpeechChannel ****************/

SpeechChannel OpenOneSpeechChannel( void )
{
  SpeechChannel channel;  
  OSErr     err;

  err = NewSpeechChannel( nil, &channel );

  if ( err != noErr )
  {
   err = DisposeSpeechChannel( channel );
   channel = nil;
  }

  return ( channel );
}

DoError() is unchanged from prior versions. A call to this function results in the posting of an alert that holds an error message. After the alert is dismissed the program ends.

/********************** DoError **********************/

void		DoError( Str255 errorString )
{
	ParamText( errorString, "\p", "\p", "\p" );

	StopAlert( kALRTResID, nil );

	ExitToShell();
}

Running SpeechChan

Run SpeechChan by choosing Run from CodeWarrior's Project menu. After the code is compiled, CodeWarrior runs the program. After the program speaks a single phrase, the program ends. If the program successfully builds and appears to run and quit without speaking, then there's a good chance you have the speaker volume on your Mac set to 0!

Till Next Month...

Last month you saw how your program can speak the text in a single string. Here you saw how your program can speak a greater amount of text by way of a buffer. You also saw how to create a speech channel. Next month we'll wrap up the topic of speech by discussing how you can specify which voice - male, female, young, old, even robotic - you want your program to speak in. Until then you can study up on speech generation by looking at the Sound volume of Inside Macintosh...

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Printopia 3.0.4 - Share Mac printers wit...
Run Printopia on your Mac to share its printers to any capable iPhone, iPad, or iPod Touch. Printopia will also add virtual printers, allowing you to save print-outs to your Mac and send to apps.... Read more
Tinderbox 7.3.1 - Store and organize you...
Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
ExpanDrive 6.1.6 - Access cloud storage...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
Printopia 3.0.4 - Share Mac printers wit...
Run Printopia on your Mac to share its printers to any capable iPhone, iPad, or iPod Touch. Printopia will also add virtual printers, allowing you to save print-outs to your Mac and send to apps.... Read more
Tinderbox 7.3.1 - Store and organize you...
Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
ExpanDrive 6.1.6 - Access cloud storage...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
VOX 3.0.1 - Music player that supports m...
VOX just sounds better! The beauty is in its simplicity, yet behind the minimal exterior lies a powerful music player with a ton of features and support for all audio formats you should ever need.... Read more
Merlin Project 4.3.3 - $289.00
Merlin Project is the leading professional project management software for OS X. If you plan complex projects on your Mac, you won’t get far with a simple list of tasks. Good planning raises... Read more
Mac DVDRipper Pro 7.1 - Copy, backup, an...
Mac DVDRipper Pro is the DVD backup solution that lets you protect your DVDs from scratches, save your batteries by reading your movies from your hard disk, manage your collection with just a few... Read more
iMazing 2.5.2 - Complete iOS device mana...
iMazing (was DiskAid) is the ultimate iOS device manager with capabilities far beyond what iTunes offers. With iMazing and your iOS device (iPhone, iPad, or iPod), you can: Copy music to and from... Read more

Latest Forum Discussions

See All

148Apps' Ultimate Guide to Black Fr...
Black Friday is here, and there are a whole lot of discounts running right now for folks on the lookout for new mobile devices, accessories, and yes, even games. Here's a helpful rundown of what you'll find both in stores and online. Happy... | Read more »
The best Black Friday mobile game deals
Black Friday's upon us, and if you've happened to nab a fancy new phone during the week's big savings, you might be searching for some new games to fill up space on your new gadget. There are a lot of great games on sale right now for Black Friday... | Read more »
The best mobile games to play while your...
Thanksgiving is a time to reconnect with loved ones, eat lots of food, and all of that jazz, but once the festivities start to wind down, folks tend to head to the couch to watch whatever football is happening for Turkey Day. | Read more »
The best Black Friday deals for Apple ga...
Black Friday is hours away at this point, but many popular retailers are getting a jump on things with plenty of pre-Black Friday sales already available. Many of those early bird sales including some sharp discounts on the latest Apple phones... | Read more »
The Inner World 2 (Games)
The Inner World 2 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Solve mind-bending puzzles in a world full of mystery and save the family of the flute-noses! Their dynasty has been... | Read more »
warbot.io wants you for the robot wars
Fans of epic gundam-style battles will find a lot to love in warbot.io, the first game for up and coming developer Wondersquad. The game saw a lot of success when it first launched for browsers and Facebook, and now even more people are getting the... | Read more »
Uncover alien mysteries in cross-genre s...
If the Alien franchise taught us anything, it’s that landing on a strange planet at the behest of a faceless corporation is probably asking for trouble. And Eldritch Game’s Deliria doesn’t prove otherwise. In 2107, Dimension LG7 is rich with... | Read more »
The best mobile games to play during dre...
| Read more »
Animal Crossing: Pocket Camp beginner...
Animal Crossing: Pocket Camp, was just announced yesterday, but it's already in soft launch in Australia. No matter where you are in the world, you can still get access to the soft launch on iOS, so we've devised a few beginner tips for folks who... | Read more »
The mobile gamer's guide to Black F...
We're starting to catch wind of some exciting deals in the mobile gaming space for Black Friday. There are big discounts on mobile phones and accessories cropping up already, so you might want to get a move on things ahead of the big day. It's... | Read more »

Price Scanner via MacPrices.net

Apple Black Friday sale for 2017: $150 Apple...
BLACK FRIDAY Apple has posted their Black Friday deals for 2017. Receive a $150 Apple gift card with the purchase of select Macs and up to $100 with various iPads, iPhones, and Apple Watches. The... Read more
Black Friday 2017: Where to find the best dea...
B&H Photo has 15″ and 13″ MacBook Pros on sale for up to $200 off MSRP as part of the Black Friday and Holiday sale. Shipping is free, and B&H charges sales tax for NY & NJ residents only... Read more
Black Friday 2017: Where to find the best dea...
B&H Photo has 12″ MacBooks on sale for $150 off MSRP as part of the Black Friday and Holiday sale. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 12″ 1.2GHz... Read more
Black Friday 2017: Where to find the best dea...
B&H Photo has 10.5″ iPad Pros in stock today and on sale for up to $130 off MSRP. Each iPad includes free shipping, and B&H charges sales tax in NY & NJ only: – 10.5″ 64GB WiFi iPad Pro... Read more
Black Friday 2017: Where to find the best dea...
B&H Photo has 13″ MacBook Airs on sale for up to $150 off MSRP as part of the Black Friday and Holiday sale. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13″... Read more
Black Friday 2017: Where to find the best dea...
B&H Photo has 27″ and 21″ iMacs on sale for up to $200 off MSRP as part of the Black Friday and Holiday sale. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 27... Read more
Black Friday 2017: Where to find the best dea...
B&H Photo has Mac minis on sale for $100 off MSRP as part of their Black Friday sale, each including free shipping plus NY & NJ sales tax only: – 1.4GHz Mac mini: $399 $100 off MSRP – 2.6GHz... Read more
Black Friday 2017: Find the best deals and lo...
Scan our exclusive price trackers for the latest Black Friday 2017 sales & deals and the lowest prices available on Apple Macs, iPads, and gear from Apple’s authorized resellers. We update the... Read more
Black Friday: 27″ 3.4GHz iMac for $1599, save...
Amazon has the 27″ 3.4GHz Apple iMac on sale for $1599.99 as part of their Black Friday sale. That’s $200 off MSRP, and shipping is free. Their price is currently the lowest price available for this... Read more
Black Friday: 13″ 2.3GHz/256GB MacBook Pro fo...
Amazon has the 13″ 2.3GHz/256GB Apple MacBook Pro on sale for $1299.99 as part of their Black Friday sale. Shipping is free: – 13-inch 2.3GHz/256GB Space Gray MacBook Pro (MPXT2LL/A): $1299.99 $200... Read more

Jobs Board

Business Development Manager, *Apple* Pay -...
# Business Development Manager, Apple Pay Job Number: 112919084 Santa Clara Valley, California, United States Posted: 18-Aug-2017 Weekly Hours: 40.00 **Job Summary** Read more
Digital Marketing Media Planner, *Apple* Se...
# Digital Marketing Media Planner, Apple Services Job Number: 113080212 Culver City, California, United States Posted: 03-Oct-2017 Weekly Hours: **Job Summary** Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Business Development Manager, *Apple* Pay -...
# Business Development Manager, Apple Pay Job Number: 112919084 Santa Clara Valley, California, United States Posted: 18-Aug-2017 Weekly Hours: 40.00 **Job Summary** Read more
*Apple* Solutions Consultant - Apple (United...
# Apple Solutions Consultant Job Number: 56553863 North Wales, Pennsylvania, United States Posted: 17-Jun-2017 Weekly Hours: 40.00 **Job Summary** Are you passionate Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.