Skip to content
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
3 changes: 1 addition & 2 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Bug report
description: Report a reproducible defect in dart_modem.
description: Report a reproducible defect in flutter_modem.
title: "[Bug]: "
labels: [bug]
body:
Expand Down Expand Up @@ -43,4 +43,3 @@ body:
options:
- label: I searched existing issues for duplicates.
required: true

3 changes: 1 addition & 2 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security report
url: https://github.com/bchainhub/dart_modem/security/advisories/new
url: https://github.com/DataLayerHost/flutter_modem/security/advisories/new
about: Report vulnerabilities privately instead of opening a public issue.

7 changes: 5 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Dart CI
name: Testing

on:
push:
Expand All @@ -11,11 +11,14 @@ permissions:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: dart-lang/setup-dart@v1
with:
sdk: stable
- run: dart pub get
- run: dart format --output=none --set-exit-if-changed .
- run: dart analyze --fatal-infos
- run: dart test

- run: dart pub publish --dry-run
16 changes: 15 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,21 @@ on:
- "[0-9]+.[0-9]+.[0-9]+"

jobs:
publish:
validate:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: dart-lang/setup-dart@v1
with:
sdk: stable
- run: dart pub get
- run: dart format --output=none --set-exit-if-changed .
- run: dart analyze --fatal-infos
- run: dart test
- run: dart pub publish --dry-run
publish-pub-dev:
needs: validate
permissions:
id-token: write
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.2.0

- Rename the package and public library from `dart_modem` to `flutter_modem`.
- Move repository and issue links to DataLayerHost/flutter_modem.
- Align continuous integration and publishing checks with the related Flutter packages.

## 0.1.0

- Initial release with a pure Dart continuous-phase BFSK encoder.
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DART MODEM
# Flutter Modem

`dart_modem` is a pure Dart acoustic modem. It turns arbitrary bytes into signed
`flutter_modem` is a pure Dart acoustic modem. It turns arbitrary bytes into signed
16-bit PCM audio and incrementally reconstructs validated packets from PCM. The
core has no Flutter, native-code, audio-device, or runtime-specific dependency,
so it can be used on the Dart VM, servers, Flutter, and Dart-to-Wasm targets.
Expand All @@ -10,9 +10,9 @@ so it can be used on the Dart VM, servers, Flutter, and Dart-to-Wasm targets.
```dart
import 'dart:convert';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

final modem = DartModem(modulation: const Bfsk());
final modem = FlutterModem(modulation: const Bfsk());
final pcm = modem.encode(utf8.encode('Hello'));

final decoder = modem.createStreamingDecoder();
Expand All @@ -27,13 +27,13 @@ to the host application, which keeps the modem platform-independent.

## Application protocol

`DartModem` uses Voice Transaction Protocol version 1 by default. Each input is
`FlutterModem` uses Voice Transaction Protocol version 1 by default. Each input is
treated as an already-signed transaction, wrapped in a SHA-256/CRC-protected
envelope, split into Voice TX DATA packets, and reassembled by the matching
decoder. Configure the chain identifiers for production use:

```dart
final modem = DartModem(
final modem = FlutterModem(
protocol: const VoiceTxModemProtocol(
blockchainId: 1,
networkId: 1,
Expand All @@ -44,15 +44,15 @@ final modem = DartModem(
The default identifiers are zero when the application does not supply them.
Empty payloads are invalid under Voice TX. The complete Voice TX packet,
envelope, assembly, and sender/receiver session APIs are exported directly by
`dart_modem`.
`flutter_modem`.

To use only the modem's basic `DMOD` transport framing, disable the application
protocol explicitly:

```dart
final rawModem = DartModem(protocol: null);
final rawModem = FlutterModem(protocol: null);
// Equivalent when a non-null ModemProtocol value is needed:
final identityModem = DartModem(protocol: const NoModemProtocol());
final identityModem = FlutterModem(protocol: const NoModemProtocol());
```

Another protocol can replace Voice TX by implementing `ModemProtocol` and its
Expand Down Expand Up @@ -88,7 +88,7 @@ For hardware with a usable high-frequency audio path, select the built-in
near-ultrasonic preset:

```dart
final modem = DartModem(
final modem = FlutterModem(
modulation: const Bfsk.ultrasonic(),
);

Expand All @@ -115,7 +115,7 @@ For noisy, filtered, or codec-damaged calls where throughput is less important,
use the 100-baud poor-quality profile:

```dart
final modem = DartModem(
final modem = FlutterModem(
modulation: const Bfsk.poorQuality(),
);
```
Expand All @@ -128,7 +128,7 @@ It uses 8 kHz PCM with 1200/2200 Hz tones and 80 samples per bit. The older
The `fast` preset is an alternative 1200-baud audible channel:

```dart
final modem = DartModem(
final modem = FlutterModem(
modulation: const Bfsk.fast(),
);

Expand Down Expand Up @@ -199,13 +199,13 @@ add gain control, filtering, echo, clock drift, clipping, and noise. Resample
captured audio to the configured rate and supply mono signed Int16 PCM. Test the
chosen frequencies and baud rate against the actual channel before deployment.

The waveform uses V.23-compatible frequencies and bitrate, but dart_modem's
The waveform uses V.23-compatible frequencies and bitrate, but flutter_modem's
packet framing is its own protocol; it does not claim byte-level interoperability
with legacy V.23 terminals. Speech codecs, echo cancellation, automatic gain
control, and noise suppression can still damage modem audio. An uncompressed
G.711 path is preferable where the call stack exposes that choice.

`dart_modem` only generates and analyzes waveforms. A Flutter application can
`flutter_modem` only generates and analyzes waveforms. A Flutter application can
connect it to any suitable audio capture/playback package without coupling that
package to the modem core.

Expand Down Expand Up @@ -239,7 +239,7 @@ listening, and permits transmission after a decoded guard delay.
Receiver answers
→ receiver repeats READY
→ phone microphone captures READY
dart_modem detects READY
flutter_modem detects READY
→ app waits guard delay
→ app plays transaction audio
→ receiver stops READY transmission when transaction preamble is detected
Expand Down Expand Up @@ -275,7 +275,7 @@ behavior implemented in this release.
### Receiver/server generation

```dart
final modem = DartModem();
final modem = FlutterModem();
final ready = ReadySignal(
sessionId: secureSessionId,
guardDelay: const Duration(milliseconds: 500),
Expand Down
2 changes: 1 addition & 1 deletion example/decode_hello.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

Future<void> main() async {
final Int16List pcm = BfskEncoder().encode(utf8.encode('Hello'));
Expand Down
2 changes: 1 addition & 1 deletion example/encode_hello.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

void main() {
final Int16List pcm = BfskEncoder().encode(utf8.encode('Hello'));
Expand Down
4 changes: 2 additions & 2 deletions example/encode_random_bytes.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import 'dart:math';
import 'dart:typed_data';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

void main() {
final Random random = Random.secure();
final Uint8List payload =
Uint8List.fromList(List<int>.generate(32, (_) => random.nextInt(256)));
final Int16List pcm = DartModem().encode(payload);
final Int16List pcm = FlutterModem().encode(payload);
print('Payload: ${bytesToHex(payload)}');
print('PCM samples: ${pcm.length}');
}
4 changes: 2 additions & 2 deletions example/fast_loopback.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:convert';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

void main() {
final DartModem modem = DartModem(modulation: const Bfsk.fast());
final FlutterModem modem = FlutterModem(modulation: const Bfsk.fast());
final List<int> sent = utf8.encode('Fast acoustic modem');
final List<ModemFrame> received = modem.createDecoder().feed(
modem.encode(sent),
Expand Down
6 changes: 6 additions & 0 deletions example/flutter_modem_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import 'package:flutter_modem/flutter_modem.dart';

void main() {
final samples = BfskEncoder().encode(const [0x48, 0x69]);
print('Generated ${samples.length} PCM samples.');
}
4 changes: 2 additions & 2 deletions example/loopback.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:convert';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

void main() {
final DartModem modem = DartModem(modulation: const Bfsk());
final FlutterModem modem = FlutterModem(modulation: const Bfsk());
final List<int> sent = utf8.encode('Acoustic loopback');
final List<ModemFrame> received =
modem.createDecoder().feed(modem.encode(sent));
Expand Down
4 changes: 2 additions & 2 deletions example/ready_phone_flow.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

final DartModem modem = DartModem();
final FlutterModem modem = FlutterModem();
final Int16List preparedTransactionPcm = modem.encode(
utf8.encode('Prepared transaction'),
);
Expand Down
4 changes: 2 additions & 2 deletions example/ready_server.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:typed_data';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

void main() {
final DartModem modem = DartModem();
final FlutterModem modem = FlutterModem();
final RepeatingReadySignalEncoder repeater = RepeatingReadySignalEncoder(
modem: modem,
ready: const ReadySignal(
Expand Down
4 changes: 2 additions & 2 deletions example/ultrasonic_loopback.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:convert';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';

void main() {
final DartModem modem = DartModem(
final FlutterModem modem = FlutterModem(
modulation: const Bfsk.ultrasonic(),
);
final List<int> sent = utf8.encode('Near-ultrasonic Hello');
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions lib/src/control/ready_signal_encoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ final class ReadySignalEncoderConfig {
final Duration trailingSilence;
}

/// Adds acoustic padding and encodes READY through a [DartModem].
/// Adds acoustic padding and encodes READY through a [FlutterModem].
final class ReadySignalEncoder {
const ReadySignalEncoder({
required this.modem,
this.config = const ReadySignalEncoderConfig(),
});

final DartModem modem;
final FlutterModem modem;
final ReadySignalEncoderConfig config;

Int16List encode(ReadySignal ready) {
Expand Down Expand Up @@ -85,7 +85,7 @@ final class RepeatingReadySignalEncoder {
_validate();
}

final DartModem modem;
final FlutterModem modem;
final ReadySignal ready;
final ReadyRepeatConfig config;
final ReadySignalEncoderConfig encoderConfig;
Expand Down
4 changes: 2 additions & 2 deletions lib/src/decoder/protocol_decoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ final class ProtocolModemDecoder implements ModemFrameDecoder {
}

/// Push-based protocol-aware modem decoder.
final class StreamingDartModemDecoder implements ModemFrameDecoder {
StreamingDartModemDecoder(this._decoder);
final class StreamingFlutterModemDecoder implements ModemFrameDecoder {
StreamingFlutterModemDecoder(this._decoder);

final ModemFrameDecoder _decoder;
final StreamController<ModemFrame> _controller =
Expand Down
8 changes: 4 additions & 4 deletions lib/src/modem.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import 'encoder/bfsk_encoder.dart';
import 'protocol/modem_protocol.dart';

/// Convenient facade for encoding and creating matching decoders.
final class DartModem {
DartModem({
final class FlutterModem {
FlutterModem({
this.modulation = const Bfsk(),
this.protocol = const VoiceTxModemProtocol(),
});
Expand Down Expand Up @@ -57,6 +57,6 @@ final class DartModem {
);
}

StreamingDartModemDecoder createStreamingDecoder() =>
StreamingDartModemDecoder(createDecoder());
StreamingFlutterModemDecoder createStreamingDecoder() =>
StreamingFlutterModemDecoder(createDecoder());
}
4 changes: 2 additions & 2 deletions lib/src/protocol/modem_protocol.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ abstract interface class ModemProtocolDecoder {
void reset();
}

/// Version 1 Voice Transaction Protocol, used by [DartModem] by default.
/// Version 1 Voice Transaction Protocol, used by [FlutterModem] by default.
///
/// The input to [encode] is an already-signed, publicly broadcastable
/// transaction. It is enveloped, hashed, checksummed, and split into bounded
Expand Down Expand Up @@ -102,7 +102,7 @@ final class _VoiceTxModemProtocolDecoder implements ModemProtocolDecoder {

/// Identity application protocol.
///
/// This is equivalent to passing `protocol: null` to [DartModem], and is
/// This is equivalent to passing `protocol: null` to [FlutterModem], and is
/// useful where a concrete [ModemProtocol] value is required.
final class NoModemProtocol implements ModemProtocol {
const NoModemProtocol();
Expand Down
8 changes: 4 additions & 4 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: dart_modem
name: flutter_modem
description: A pure Dart acoustic modem for encoding binary data as BFSK PCM audio.
version: 0.1.0
repository: https://github.com/bchainhub/dart_modem
issue_tracker: https://github.com/bchainhub/dart_modem/issues
version: 0.2.0
repository: https://github.com/DataLayerHost/flutter_modem
issue_tracker: https://github.com/DataLayerHost/flutter_modem/issues
topics:
- audio
- modem
Expand Down
2 changes: 1 addition & 1 deletion test/bytes_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';
import 'package:test/test.dart';

void main() {
Expand Down
2 changes: 1 addition & 1 deletion test/crc32_test.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'dart:convert';

import 'package:dart_modem/dart_modem.dart';
import 'package:flutter_modem/flutter_modem.dart';
import 'package:test/test.dart';

void main() {
Expand Down
Loading
Loading