1. 程式人生 > >如何使用 iOS 7 的 AVSpeechSynthesizer 製作有聲書(4)

如何使用 iOS 7 的 AVSpeechSynthesizer 製作有聲書(4)

控制:我們必須學會控制

大師尤達(電影《星球大戰》)曾有言:關鍵在於控制。這本故事書是一個詞一個詞地念出來的,我準備為它增加兩個按鈕,這樣我們就可以實時地調整語音合成時的音高和語速。

仍然是 RWTPageViewController.m,在nextSpeechIndex 屬性後宣告下列屬性:

@property (nonatomic, assign) float currentPitchMultiplier;

@property (nonatomic, assign) float currentRate;

在 gotoPreviousPage:方法後增加如下方法:

- (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];

     }

}

這些方法將和語音控制面板上的按鈕相連線。

  • lowerPitch: 和 raisePitch: 方法用於降低和提高音高,每次都會在原有基礎上減低或增加20%,但該值會限定在(0.5-2.0)之間。
  • lowerRate: 和 raiseRate 方法用於降低和提高朗讀的語速,每次會在原有基礎上+/- 20%,總體範圍限定在 AVSpeechUtteranceMinimumSpeechRate 和 AVSpeechUtteranceMaximumSpeechRate 之間。
  • speakAgain: 重置當前語句的索引值,並再次顯示相應的文字內容。

建立按鈕,然後在 raiseRate 方法後加入下列方法:

-(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(52, 485, 150, 50)

                              title:@"Lower Pitch"

                             action:@selector(lowerPitch)];

   [self addSpeechControlWithFrame:CGRectMake(222, 485, 150, 50)

                              title:@"Raise Pitch"

                             action:@selector(raisePitch)];

   [self addSpeechControlWithFrame:CGRectMake(422, 485, 150, 50)

                              title:@"Lower Rate"

                             action:@selector(lowerRate)];

   [self addSpeechControlWithFrame:CGRectMake(592, 485, 150, 50)

                              title:@"Raise Rate"

                             action:@selector(raiseRate)];

   [self addSpeechControlWithFrame:CGRectMake(506, 555, 150, 50)

                              title:@"Speak Again"

                             action:@selector(speakAgain)];  

}

addSpeechControlWithFrame:方法是一個便利方法,用於在檢視中新增一個按鈕並將其與相應的方法連線起來,這樣就可以通過按鈕來調整語音。

注意:也可以在 Main.storyboard 中建立按鈕並繫結他們的action 到 RWTPageViewController。這樣更容易,效率也更高。

在 viewDidLoad 的 [self startSpeaking] 方法之前加入:

    // 1

   self.currentPitchMultiplier = 1.0f;

   self.currentRate = AVSpeechUtteranceDefaultSpeechRate;

     // 2

   [self addSpeechControls];

註釋“1”處設定預設的語音屬性,註釋“2”處則新增語音控制按鈕。

 最後,修改  speakNextUtterance    方法:

- (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];

   }

}

如果你點選了 lower/raise 按鈕,則新設定的值將在下一句朗讀中得到應用。

編譯執行。如下圖所示:

觸控或點選這些按鈕,然後注意發音的變化。尤達確實很厲害,哪怕你不是傑迪也可以成為大師(AVSpeechSynthesizer 方面的)。

結尾

希望本文能成為激發你開發自己的有聲書的動力。如果你想知道更多的關於如何對合成語音進行調優的技巧,請看下面:

最佳有聲書WhirlySquirrelly.plist競賽

說明:請嘗試進一步調優 WhirlySquirrelly.plist,並上傳至論壇或者本文留言裡。我們會評出其中的優勝者,並在評論中加以褒揚。

允許使用者選擇圖書

說明: 新增一個“Choose Book” 按鈕,並在 UIPopoverController中顯示一個可選的圖書列表。當用戶選擇某本圖書,在 RWTPageViewController 中重置 book 物件並顯示新書。

從 Web 上下載圖書

說明:將書籍以 plist 格式儲存在 web伺服器或者提供類似 AWS S3 或者 Heroku 的服務。伺服器先要提供一個 url列表,列出所有圖書,然後再提供一個可以下載某本書的服務。在前一個功能中,將圖書的連結新增進去。

唸到詞高亮顯示

提示: 使用AVSpeechSynthesizerDelegate 委託中的方法

在 speechSynthesizer:didStartSpeechUtterance:方法中,高亮指定的 utterance。

在 speechSynthesizer:didFinishSpeechUtterance:方法中,將高亮的 utterance 去高亮。你可以用 pageTextLable 的 attributedText 屬性,通過NSAttributedString 設定不同的背景色和字型屬性以實現加亮效果。

在第一頁顯示書名

Addthe Ability to Display a Title Page Before All Other Pages

說明:在 RWTPageViewController 之前加入額外的 viewController,並設定 Main.storyboard 屬性已啟用新的viewcontroller。將兩個 ViewController 用一個 UINavigationController 管理起來。 為此,你可以修改 Page 類的設計,並分為有聲的 Page 和無聲的 Page,然後修改 RWTPageViewController 讓它能夠處理這兩種不同的Page。