トップ «前の日記(2012-02-24) 最新 次の日記(2012-02-26)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|

2012-02-25 [Mac]談話と特殊効果(Text-to-Speech)

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);

トップ «前の日記(2012-02-24) 最新 次の日記(2012-02-26)» 編集