Skip to content
Open
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
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ On small patches, the patch version of this package will increase, if a new Opus
<a name="choosing_bindings"></a>
### The Bindings
There are automatically generated bindings for most functions of the Opus include headers.
Variadic (especially the CTL) functions are [not supported](https://github.com/dart-lang/sdk/issues/38578) in Dart at the moment,
so they are missing, as well as makros.
The generated bindings can all be found in the /wrappers section and are named after the group they are from.
Documentation of the bounded functions was copied from the Opus headers (and is thus not very well formated).
For sake of completeness the tool folder contains the code that was used for generation. NOTE that [ffi_tool](https://github.com/dart-interop/ffi_tool) ^0.4.0 is needed for generation, which might not be yet available on pub, so it's used directly from GitHub. Also, since in the meantime a somewhat official package to create ffi bindings - [ffigen](https://pub.dev/packages/ffigen) - emerged, this should be used to generate bindings for further opus versions.
Expand Down Expand Up @@ -141,4 +139,26 @@ void main(){
initOpus(await opus_flutter.load());
print(getOpusVersion());
}
```


<a name="init_encoder_ctl"></a>
### Encoder CTL
To perform a CTL function on an Opus encoder, you can use encoderCtl() with the request and the value. Please note that although encoderCtl allows variadic arguments in the original Opus library, the dart implementation only allows one argument. This is fine for most use cases.
Be sure to include opus_defines.dart as it contains all the request names.
```dart
import 'package:opus_dart/opus_dart.dart';
import 'package:opus_dart/wrappers/opus_defines.dart';
import 'package:opus_flutter/opus_flutter.dart' as opus_flutter;

static const AUDIO_CHANNELS = 1;
static const SAMPLE_RATE = 8000;
static const OPUS_BITRATE = 15200;

SimpleOpusEncoder openCbrEncoder() {
final opusEncoder = SimpleOpusEncoder(sampleRate: SAMPLE_RATE, channels: AUDIO_CHANNELS, application: Application.restrictedLowdely);
opusEncoder.encoderCtl(request: OPUS_SET_VBR_REQUEST, value: 0);
opusEncoder.encoderCtl(request: OPUS_SET_BITRATE_REQUEST, value: OPUS_BITRATE);
return opusEncoder;
}
```
12 changes: 12 additions & 0 deletions lib/src/opus_dart_encoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ class SimpleOpusEncoder extends OpusEncoder {
}
}

int encoderCtl(
{required int request, required int value}) {
int ret = opus.encoder.opus_encoder_ctl(_opusEncoder, request, value);
try {
if (ret != opus_defines.OPUS_OK) {
throw OpusException(ret);
}
} finally {
}
return ret;
}

/// Encodes a frame of pcm data, stored as Int16List.
///
/// [input] needs to contain a valid count of samples for the opus codec.
Expand Down
2 changes: 1 addition & 1 deletion lib/wrappers/opus_decoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import '../src/proxy_ffi.dart' as ffi;
/// This contains the complete state of an Opus decoder.
/// It is position independent and can be freely copied.
/// @see opus_decoder_create,opus_decoder_init
class OpusDecoder extends ffi.Opaque {}
final class OpusDecoder extends ffi.Opaque {}

typedef _opus_decoder_get_size_C = ffi.Int32 Function(
ffi.Int32 channels,
Expand Down
41 changes: 39 additions & 2 deletions lib/wrappers/opus_encoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import '../src/proxy_ffi.dart' as ffi;
/// This contains the complete state of an Opus encoder.
/// It is position independent and can be freely copied.
/// @see opus_encoder_create,opus_encoder_init
class OpusEncoder extends ffi.Opaque {}
final class OpusEncoder extends ffi.Opaque {}

typedef _opus_encoder_get_size_C = ffi.Int32 Function(
ffi.Int32 channels,
Expand Down Expand Up @@ -83,6 +83,11 @@ typedef _opus_encoder_destroy_Dart = void Function(
);

class FunctionsAndGlobals {
/// Holds the symbol lookup function.
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
_lookup;


FunctionsAndGlobals(ffi.DynamicLibrary _dynamicLibrary)
: _opus_encoder_get_size = _dynamicLibrary.lookupFunction<
_opus_encoder_get_size_C, _opus_encoder_get_size_Dart>(
Expand All @@ -107,7 +112,8 @@ class FunctionsAndGlobals {
_opus_encoder_destroy = _dynamicLibrary.lookupFunction<
_opus_encoder_destroy_C, _opus_encoder_destroy_Dart>(
'opus_encoder_destroy',
);
),
_lookup = _dynamicLibrary.lookup;

/// Gets the size of an <code>OpusEncoder</code> structure.
/// @param [in] channels <tt>int</tt>: Number of channels.
Expand Down Expand Up @@ -278,4 +284,35 @@ class FunctionsAndGlobals {
}

final _opus_encoder_destroy_Dart _opus_encoder_destroy;

/// Perform a CTL function on an Opus encoder.
///
/// Generally the request and subsequent arguments are generated
/// by a convenience macro.
/// @param st <tt>OpusEncoder*</tt>: Encoder state.
/// @param request This and all remaining parameters should be replaced by one
/// of the convenience macros in @ref opus_genericctls or
/// @ref opus_encoderctls.
/// @see opus_genericctls
/// @see opus_encoderctls
int opus_encoder_ctl(
ffi.Pointer<OpusEncoder> st,
int request,
int va,
) {
return _opus_encoder_ctl(
st,
request,
va,
);
}

late final _opus_encoder_ctlPtr = _lookup<
ffi.NativeFunction<
ffi.Int Function(ffi.Pointer<OpusEncoder>, ffi.Int,
ffi.VarArgs<(ffi.Int,)>)>>('opus_encoder_ctl');
late final _opus_encoder_ctl = _opus_encoder_ctlPtr
.asFunction<int Function(ffi.Pointer<OpusEncoder>, int, int)>();


}