iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
WWDCに行くと、どんな方向を目指しているのか感じ取る事が出来る。また、その場で理解できなくても、これは聞いた事があるな?と、調査のヒントを得られる。今回は、WWDCが解決の糸口になった例だ。
OS Xでテキストの内容をスピーチされる事は簡単だ。
Cocoaでは、
NSSpeechSynthesizer *synthesizer = [[NSSpeechSynthesizer alloc] init];
[synthesizer setDelegate:self];
[synthesizer startSpeakingString:@"Hello, world."];
- (void)speehSynthesizer:(NSSpeechSynthesizer *)sender
didFinishSpeaking:(BOOL)finishedpeaking
{
...
}
Core Foundationでは、
SpeechChannel *chan;
err = NewSpeechChannel(NULL, &chan);
CFNumber *callback = CFNumberCreate(NULL, kCFNumberLongType, HighlightSpokenWord);
err = SetSpeechProperty(chan, kSpeechWordCFCallBack, callback);
err = SpeakCFString(chan, CFSTR("Hello, world."), NULL);
void HighlightSpokenWord(SpeechChannel chan,
SRefCo refCon,
CFStringRef aString,
CFRange wordRange)
{
....
}
でも、それにAudio Unitを使った効果を適用させるには、どうすればいいのか?
どうして、これが出来ると思ったのかは今となっては思い出せないが、多分、WWDCでのセッションの内容が頭の片隅にあったのだろう。それで、WWDCのセッションのビデオを見直しのが、WWDC2009のSession 129『Text-to-Speech: Adventures with Alex』だった。
一度、解決の糸口をつかむと、後は芋づる式。ヘッダーファイルのコメントで説明されていた。
SpeechSynthesis.h
/*------------------------------------------*/
/* AudioUnit constants - new in 10.5 */
/*------------------------------------------*/
enum {
kAudioUnitSubType_SpeechSynthesis = 'ttsp', /* kAudioUnitType_Generator */
kAudioUnitProperty_Voice = 3330, /* Get/Set (VoiceSpec) */
kAudioUnitProperty_SpeechChannel = 3331 /* Get (SpeechChannel) */
};
指定した文章をSpeech Synthesisで喋らせ、それをAudio Unitのコンポーネントでディレイさせて再生させる例が以下だ。
AUNode inputNode, effectNode, outputNode;
NewAUGraph(&_auGraph);
AudioComponentDescription cd;
cd.componentType = kAudioUnitType_Generator;
cd.componentSubType = kAudioUnitSubType_SpeechSynthesis;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
AUGraphAddNode(_auGraph, &cd, &inputNode);
cd.componentType = kAudioUnitType_Effect;
cd.componentSubType = kAudioUnitSubType_Delay;
AUGraphAddNode(_auGraph, &cd, &effectNode);
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_DefaultOutput;
AUGraphAddNode(_auGraph, &cd, &outputNode);
AUGraphConnectNodeInput(_auGraph, inputNode, 0, effectNode, 0);
AUGraphConnectNodeInput(_auGraph, effectNode, 0, outputNode, 0);
AUGraphOpen(_auGraph);
AUGraphInitialize(_auGraph);
AudioUnit generateAudioUnit;
AUGraphNodeInfo(_auGraph, inputNode, NULL, &generateAudioUnit);
SpeechChannel channel;
UInt32 sz = sizeof(SpeechChannel);
AudioUnitGetProperty(generateAudioUnit, kAudioUnitProperty_SpeechChannel,
kAudioUnitScope_Global, 0, &channel, &sz);
AUGraphStart(_auGraph);
SpeakCFString(channel, CFSTR("Hello, world."), NULL);