Integrating ASR with SudMGP SDK in Small Games (iOS)
SudMGP provides interactive small games such as "Draw and Guess," "Speak and Guess," and "Number Bomb," supporting players to interact using voice commands to enhance playability and social attributes. The integration steps for incorporating ASR functionality into the SudMGP SDK are straightforward. This article outlines the steps for integrating ASR functionality into small games using the SudMGP SDK.
1. Background
Small games can be equipped with voice interaction capabilities. Apps need to obtain specific PCM data formats from the Agora RTC and pass them into the SudMGP SDK in a specified manner. Taking "hello-sud-plus-ios" as an example, the source code is available at: https://github.com/SudTechnology/hello-sud-plus-ios. "hello-sud-plus-ios" encapsulates the SudMGP SDK with SudMGPWrapper, and we recommend clients to integrate the SDK using SudMGPWrapper.
2. Integration Steps
SDK GitHub repository: https://github.com/SudTechnology/sud-mgp-ios. Please use the latest version available. Integration can be done via CocoaPods. Here's an example using version 1.3.4.1290:
Integrate the SudMGP SDK:
- Standard version:
pod 'SudMGPWrapper', '~> 1.3.4.1'
- Lite version:
pod 'SudMGPWrapper_Lite', '~> 1.3.4.1'
- Standard version:
Integrate the Speech Recognition Library:
pod 'MicrosoftCognitiveServicesSpeech-iOS', '1.23.0'
3. Starting ASR in Small Games
When a small game enters the ASR scene, ASR capability is automatically initiated. At this point, the game sends the MG_COMMON_GAME_ASR
status to the app with isOpen
set to true
. Refer to the SudFSMMGListener
protocol:
- (void)onGameMGCommonGameASR:(nonnull id <ISudFSMStateHandle>)handle model:(MGCommonGameASRModel *)model;
4. Starting RTC Audio Stream Monitoring in the App
Upon receiving the MG_COMMON_GAME_ASR
status with isOpen == YES
, the app invokes the AgoraRtcEngineKit method:
- (BOOL)setAudioFrameDelegate:(id<AgoraAudioFrameDelegate> _Nullable)delegate;
and implements the AgoraAudioFrameDelegate protocol to start capturing PCM data on the Agora side.
- Calling
[AgoraRtcEngineKit setAudioFrameDelegate:]
: ```objc /// Start capturing original audio (void)startPCMCapture { [[AsyncCallWrapper sharedInstance] addOperationWithBlock:^{
AgoraRtcEngineKit *engine = [self getEngine]; if (engine != nil) { /* Enable PCM data acquisition */ [engine setAudioFrameDelegate:self]; }
}]; } ```
AgoraAudioFrameDelegate protocol: ```objc
pragma mark - AgoraAudioFrameDelegate
- (BOOL)onRecordAudioFrame:(AgoraAudioFrame _Nonnull)frame channelId:(NSString _Nonnull)channelId {
[HSThreadUtils runOnUiThread:^{
}]; return YES; }if (self.mISudAudioEventListener != nil && [self.mISudAudioEventListener respondsToSelector:@selector(onCapturedPCMData:)]) { NSUInteger length = frame.samplesPerChannel * frame.channels * frame.bytesPerSample; NSData *pcmData = [[NSData alloc] initWithBytes:frame.buffer length:length]; [self.mISudAudioEventListener onCapturedPCMData:pcmData]; }
// Other delegate methods...
3. Passing the RTC-captured PCM data to the SDK:
```objc
/**
* Audio stream data
*/
- (void)onCapturedPCMData:(NSData *)data {
[self.sudFSTAPPDecorator pushAudio:data];
}
5. Stopping RTC Audio Stream Monitoring in the App
When the small game exits the ASR scene due to hitting or timing out, it sends a notification to the app to stop capturing PCM data. Upon receiving MG_COMMON_GAME_ASR
status with isOpen == NO
, the app calls the AgoraRtcEngineKit method [AgoraRtcEngineKit setAudioDataFrame:nil]
to close PCM data collection on the Agora side.
/// Stop capturing original audio
- (void)stopPCMCapture {
[[AsyncCallWrapper sharedInstance] addOperationWithBlock:^{
AgoraRtcEngineKit *engine = [self getEngine];
if (engine != nil) {
/* Disable PCM data acquisition */
[engine setAudioDataFrame:nil];
}
}];
}
6. Using ASR Only to Play Games
When playing games using ASR only, the app only needs to handle the MG_COMMON_GAME_ASR
status, responsible for starting/stopping PCM data collection on the local side. It does not need to send mg_common_key_word_to_hit
to the game like in text hit scenarios.
7. Text Input Hit Scene for Playing Small Games
Small games with speech recognition scenes usually support concurrent use of text input for hits. The game notifies the app of the hit scene start via the mg_common_key_word_to_hit
status. The app receives this notification through the SudFSMMGListener
protocol:
- (void)onGameMGCommonKeyWordToHit:(nonnull id <ISudFSMStateHandle>)handle model:(MGCommonKeyWrodToHitModel *)model;
Text hit scenes in small games are divided into two categories:
Games where the App holds the keywords: For example, "Draw and Guess," "Speak and Guess." When
model.word
is not empty, the App needs to locally determine if there's a hit. After determining the hit, the App notifies the game via the interface method[SudFSTAPPDecorator notifyAppComonDrawTextHit]
.Games where the App doesn't hold the keywords: For example, "Number Bomb." When
model.word
is empty, the App needs to send the text to the game each time for hit determination by the game.
- (void)handleGameKeywordHitting:(NSString *)content {
// Number Bomb
if (self.sudFSMMGDecorator.isHitBomb) {
if ([self isPureInt:content]) {
/// Keyword hit
[self.sudFSTAPPDecorator notifyAppComonDrawTextHit:false keyWord:@"" text:content];
}
return;
}
// Draw and Guess
if (self.sudFSMMGDecorator.keyWordHiting == YES && [content isEqualToString:self.sudFSMMGDecorator.drawKeyWord]) {
/// Keyword hit
[self.sudFSTAPPDecorator notifyAppComonDrawTextHit:true keyWord:self.sudFSMMGDecorator.drawKeyWord text:self.sudFSMMGDecorator.drawKeyWord];
}
}