Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flutter vp updates #568

Merged
merged 3 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion binding/flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@
* Additional language support added (ar, hi, nl, pl, ru, sv, vn, zh)

## [2.2.1] - 2023-06-01
* Expose Rhino properties through RhinoManager class
* Expose Rhino properties through RhinoManager class

## [2.2.2] - 2023-08-09
* Update flutter-voice-processor
112 changes: 56 additions & 56 deletions binding/flutter/lib/rhino_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ typedef InferenceCallback = Function(RhinoInference inference);
typedef ProcessErrorCallback = Function(RhinoException error);

class RhinoManager {
final VoiceProcessor? _voiceProcessor;
VoiceProcessor? _voiceProcessor;
Rhino? _rhino;

final InferenceCallback _inferenceCallback;
RemoveListener? _removeVoiceProcessorListener;
RemoveListener? _removeErrorListener;
late VoiceProcessorFrameListener _frameListener;
late VoiceProcessorErrorListener _errorListener;

bool _awaitingStop = false;
bool _isListening;

/// Rhino version string
String? get version => _rhino?.version;
Expand Down Expand Up @@ -91,88 +90,89 @@ class RhinoManager {
}

// private constructor
RhinoManager._(this._rhino, this._inferenceCallback,
RhinoManager._(this._rhino, InferenceCallback inferenceCallback,
ProcessErrorCallback? processErrorCallback)
: _voiceProcessor = VoiceProcessor.getVoiceProcessor(
_rhino!.frameLength, _rhino.sampleRate) {
if (_voiceProcessor == null) {
throw RhinoRuntimeException("flutter_voice_processor not available.");
}
_removeVoiceProcessorListener =
_voiceProcessor!.addListener((buffer) async {
if (_awaitingStop) {
return;
}

// cast from dynamic to int array
List<int> rhinoFrame;
try {
rhinoFrame = (buffer as List<dynamic>).cast<int>();
} on Error {
RhinoException castError = RhinoException(
"flutter_voice_processor sent an unexpected data type.");
processErrorCallback == null
? print(castError.message)
: processErrorCallback(castError);
: _voiceProcessor = VoiceProcessor.instance,
_isListening = false {
_frameListener = (List<int> frame) async {
if (!_isListening) {
return;
}

// process frame with Rhino
try {
RhinoInference? rhinoResult = await _rhino?.process(rhinoFrame);
RhinoInference? rhinoResult = await _rhino?.process(frame);
if ((rhinoResult != null) && (rhinoResult.isFinalized)) {
_awaitingStop = true;

_inferenceCallback(rhinoResult);
// stop audio processing
await _voiceProcessor?.stop();
inferenceCallback(rhinoResult);
await _stop();
}
} on RhinoException catch (error) {
processErrorCallback == null
? print(error.message)
? print("RhinoException: ${error.message}")
: processErrorCallback(error);
} finally {
_awaitingStop = false;
}
});

_removeErrorListener = _voiceProcessor!.addErrorListener((errorMsg) {
RhinoException nativeError = RhinoException(errorMsg as String);
};
_errorListener = (VoiceProcessorException error) {
processErrorCallback == null
? print(nativeError.message)
: processErrorCallback(nativeError);
});
? print("RhinoException: ${error.message}")
: processErrorCallback(RhinoException(error.message));
};
}

Future<void> _stop() async {
if (!_isListening) {
return;
}

_voiceProcessor?.removeErrorListener(_errorListener);
_voiceProcessor?.removeFrameListener(_frameListener);

if (_voiceProcessor?.numFrameListeners == 0) {
try {
await _voiceProcessor?.stop();
} on PlatformException catch (e) {
throw RhinoRuntimeException(
"Failed to stop audio recording: ${e.message}");
}
}

_isListening = false;
}

/// Opens audio input stream and sends audio frames to Rhino until a inference
/// result is sent via inference callback
/// Throws a `RhinoException` if there was a problem starting the audio engine
/// Starts audio recording and processing with the Rhino engine until a
/// inference result is sent via the `inferenceCallback`
/// Throws a `RhinoException` if there was a problem starting audio recording.
Future<void> process() async {
if (_isListening) {
return;
}
if (_rhino == null || _voiceProcessor == null) {
throw RhinoInvalidStateException(
"Cannot start Rhino - resources have already been released");
}

if (await _voiceProcessor?.hasRecordAudioPermission() ?? false) {
_voiceProcessor?.addFrameListener(_frameListener);
_voiceProcessor?.addErrorListener(_errorListener);
try {
await _voiceProcessor!.start();
} on PlatformException {
await _voiceProcessor?.start(_rhino!.frameLength, _rhino!.sampleRate);
} on PlatformException catch (e) {
throw RhinoRuntimeException(
"Audio engine failed to start. Hardware may not be supported.");
"Failed to start audio recording: ${e.message}");
}
} else {
throw RhinoRuntimeException(
"User did not give permission to record audio.");
}

_isListening = true;
}

/// Releases Rhino and audio resources
/// Releases Rhino and audio resources.
/// Throws a `RhinoException` if there was a problem stopping audio recording.
Future<void> delete() async {
if (_voiceProcessor?.isRecording ?? false) {
await _voiceProcessor!.stop();
}
_removeVoiceProcessorListener?.call();
_removeErrorListener?.call();
await _stop();
_voiceProcessor = null;

_rhino?.delete();
_rhino = null;
}
Expand Down
2 changes: 1 addition & 1 deletion binding/flutter/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ packages:
name: flutter_voice_processor
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.10"
version: "1.1.0"
lints:
dependency: "direct dev"
description:
Expand Down
4 changes: 2 additions & 2 deletions binding/flutter/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: rhino_flutter
description: A Flutter plugin for Picovoice's Rhino Speech-to-Intent engine
version: 2.2.1
version: 2.2.2
homepage: https://picovoice.ai/
repository: https://github.com/Picovoice/rhino/
documentation: https://picovoice.ai/docs/rhino/
Expand All @@ -14,7 +14,7 @@ dependencies:
flutter:
sdk: flutter

flutter_voice_processor: ^1.0.10
flutter_voice_processor: ^1.1.0

dev_dependencies:
flutter_test:
Expand Down
15 changes: 8 additions & 7 deletions demo/flutter/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
PODS:
- Flutter (1.0.0)
- flutter_voice_processor (1.0.6):
- flutter_voice_processor (1.1.0):
- Flutter
- ios-voice-processor (~> 1.1.0)
- integration_test (0.0.1):
- Flutter
- ios-voice-processor (1.0.3)
- ios-voice-processor (1.1.0)
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- Rhino-iOS (2.2.0):
- ios-voice-processor (~> 1.0.2)
- Rhino-iOS (2.2.2):
- ios-voice-processor (~> 1.1.0)
- rhino_flutter (2.2.0):
- Flutter
- Rhino-iOS (~> 2.2.0)
Expand Down Expand Up @@ -40,11 +41,11 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
flutter_voice_processor: afb59b604d99397a1ccf15c935ac8f2c2327f09f
flutter_voice_processor: 53afbf59ad3feb82f4a379fea9ed8dc98495210f
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
ios-voice-processor: 65b25a8db69ea25ffba0eeef37bae71a982f34cc
ios-voice-processor: 8e32d7f980a06d392d128ef1cd19cf6ddcaca3c1
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
Rhino-iOS: 5f6c2edc809a913f7559da93fc92c0e66c7bf711
Rhino-iOS: 0fad86b28d35f67ccb6bd0a2efbbcc0d88b05124
rhino_flutter: 4c3b4bbe00206617c38ea6f7c2f17d23b2879e90

PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d
Expand Down
12 changes: 5 additions & 7 deletions demo/flutter/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,7 @@ class _MyAppState extends State<MyApp> {
rhinoText = "Listening...";
});
} on RhinoException catch (ex) {
print("Failed to start audio capture: ${ex.message}");
setState(() {
isButtonDisabled = false;
});
errorCallback(ex);
}
}

Expand Down Expand Up @@ -223,7 +220,7 @@ class _MyAppState extends State<MyApp> {
margin: EdgeInsets.only(right: 10, top: 10),
child: ElevatedButton(
style: buttonStyle,
onPressed: (isButtonDisabled || isError)
onPressed: (isProcessing || isButtonDisabled || isError)
? null
: () {
_showContextInfo(context);
Expand All @@ -249,8 +246,9 @@ class _MyAppState extends State<MyApp> {
height: 130,
child: ElevatedButton(
style: buttonStyle,
onPressed:
(isButtonDisabled || isError) ? null : _startProcessing,
onPressed: (isProcessing || isButtonDisabled || isError)
? null
: _startProcessing,
child: Text(isProcessing ? "..." : "Start",
style: TextStyle(fontSize: 30)),
))),
Expand Down
4 changes: 2 additions & 2 deletions demo/flutter/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ packages:
name: flutter_voice_processor
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.10"
version: "1.1.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
Expand Down Expand Up @@ -214,7 +214,7 @@ packages:
name: rhino_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
version: "2.2.2"
sky_engine:
dependency: transitive
description: flutter
Expand Down
2 changes: 1 addition & 1 deletion demo/flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies:
flutter:
sdk: flutter

rhino_flutter: ^2.2.1
rhino_flutter: ^2.2.2

dev_dependencies:
integration_test:
Expand Down