Skip to content

Commit

Permalink
Fix analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
liamappelbe committed Dec 3, 2023
1 parent aed9ca9 commit b3cac70
Show file tree
Hide file tree
Showing 28 changed files with 269 additions and 240 deletions.
4 changes: 4 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
include: package:flutter_lints/flutter.yaml

linter:
rules:
- prefer_double_quotes
42 changes: 22 additions & 20 deletions bin/run_verifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:deep_defender/const.dart';
import 'package:deep_defender/crypto.dart';
import 'package:deep_defender/hasher.dart';
import 'package:deep_defender/metadata.dart';
import 'package:deep_defender/verifier.dart';
import 'package:wav/wav.dart';
import "dart:convert";
import "dart:io";
import "dart:math";
import "dart:typed_data";
import "package:logging/logging.dart";
import "package:deep_defender/const.dart";
import "package:deep_defender/crypto.dart";
import "package:deep_defender/verifier.dart";
import "package:wav/wav.dart";

final _log = Logger("run_verifier");

class TimedSafCode {
int timeMs;
Expand All @@ -41,7 +42,7 @@ TimedSafCode? parseSafCode(String line) {

List<TimedSafCode> parseSafCodes(String safCodes) {
final a = <TimedSafCode>[];
for (final line in safCodes.split('\n')) {
for (final line in safCodes.split("\n")) {
final saf = parseSafCode(line.trim());
if (saf != null) {
a.add(saf);
Expand All @@ -50,24 +51,25 @@ List<TimedSafCode> parseSafCodes(String safCodes) {
return a;
}

debugWav(Float64List audio, [String name = 'debug']) {
Wav([audio.sublist(0)], kSampleRate).writeFile('$name.wav');
debugWav(Float64List audio, [String name = "debug"]) {
Wav([audio.sublist(0)], kSampleRate).writeFile("$name.wav");
}

main(List<String> args) async {
if (args.length != 3) {
print('Wrong number of args. Usage:');
print(' dart run run_verifier.dart input.wav safCodes.txt key.json');
_log.severe("Wrong number of args. Usage:");
_log.severe(" dart run run_verifier.dart input.wav safCodes.txt key.json");
return;
}

final wav = await Wav.readFile(args[0]);
assert(wav.samplesPerSecond == kSampleRate);
final audio = wav.toMono();
print('Wav is ${(audio.length / kSampleRate).toStringAsFixed(2)} sec long');
_log.info(
"Wav is ${(audio.length / kSampleRate).toStringAsFixed(2)} sec long");

final safCodes = parseSafCodes(await File(args[1]).readAsString());
print('Loaded ${safCodes.length} SAF codes');
_log.info("Loaded ${safCodes.length} SAF codes");
final firstCodeTimeSec = safCodes[0].timeMs / 1000.0;
final audioStartTimeSec = max(0, firstCodeTimeSec - 2);
final audioStartSample = (audioStartTimeSec * kSampleRate).toInt();
Expand All @@ -76,11 +78,11 @@ main(List<String> args) async {
final publicKey = PublicKey.fromJwk(await File(args[2]).readAsString());

final verifier = SafCodeVerifier(publicKey, (VerifierResult result) {
print("${result.error}\t${result.score}\t${result.header?.time}");
_log.info("${result.error}\t${result.score}\t${result.header?.time}");
//final volume = Hasher.u32ToVol(
// ByteData.sublistView(result.safCode).getUint32(
// Metadata.length, Endian.big));
//print("${volume},${result.score}");
//_log.info("${volume},${result.score}");
//if (result.audio != null) {
// debugWav(result.audio!.matchedAudio, 'chunk ${result.audio!.audioTime}');
//}
Expand All @@ -89,5 +91,5 @@ main(List<String> args) async {
for (final tsc in safCodes) {
await verifier.addSafCode(tsc.safCode);
}
print('Done');
_log.info("Done");
}
13 changes: 5 additions & 8 deletions lib/bucketer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:math' as math;
import 'dart:typed_data';
import "dart:typed_data";

import 'package:fftea/fftea.dart';
import "package:fftea/fftea.dart";

import 'const.dart';
import 'util.dart';
import "util.dart";

// Receives a stream of timestamped audio data, in fixed sized chunks, runs
// STFT, and calculates power levels of coarser buckets of frequencies.
Expand All @@ -45,7 +43,6 @@ class Bucketer {
_itr = logLinItr(1 + stftSize ~/ 2, buckets, grad0: 3);

void onData(int timeMs, Float64List chunk) {
int j = 0;
_stft.run(chunk, (Float64x2List freq) {
int k = 0;
final a = freq.discardConjugates();
Expand Down Expand Up @@ -75,8 +72,8 @@ class _STFT {
_chunk = Float64x2List(chunkSize) {
if (_win != null && _win!.length != chunkSize) {
throw ArgumentError(
'Window must have the same length as the chunk size.',
'_win',
"Window must have the same length as the chunk size.",
"_win",
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/chunker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// As soon as the chunk callback is finished, the data buffer that was sent will
// be overwritten, so the callback should copy any data it needs.

import 'dart:typed_data';
import "dart:typed_data";

class Chunker {
final double _sampleRateMs;
Expand Down
2 changes: 1 addition & 1 deletion lib/const.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:typed_data';
import "dart:typed_data";

const String kMagicString = "SAF";
const int kVersion = 1;
Expand Down
11 changes: 6 additions & 5 deletions lib/crypto.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:convert';
import 'dart:typed_data';
import "dart:convert";
import "dart:typed_data";

import 'package:crypto_keys/crypto_keys.dart' as ck;
import 'package:pointycastle/src/utils.dart' show encodeBigInt, decodeBigInt;
import "package:crypto_keys/crypto_keys.dart" as ck;

import "util.dart";

/// Wrapper around crypto_keys to abstract away the details. For example, we
/// should be able to switch the crypto algorithm without changing the rest of
Expand Down Expand Up @@ -107,7 +108,7 @@ class KeyPair {
final x = _bigIntToBase64(publicKey._key.xCoordinate);
final y = _bigIntToBase64(publicKey._key.yCoordinate);
final pub = '"x":"$x","y":"$y"';
String priv = '';
String priv = "";
if (includePrivateKey) {
final d = _bigIntToBase64(privateKey._key.eccPrivateKey);
priv = ',"d":"$d"';
Expand Down
23 changes: 13 additions & 10 deletions lib/debug_file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';
import 'package:wav/wav.dart';
import 'const.dart';
import "dart:convert";
import "dart:typed_data";
import "package:logging/logging.dart";
import "package:path_provider/path_provider.dart";
import "package:wav/wav.dart";
import "const.dart";

final _log = Logger("debug_file");

// Saves an audio chunks as wav file, with its SAF code as the filename. This is
// just for debugging.
Expand All @@ -30,10 +32,11 @@ class DebugFile {
++_debugIndex;
final audioCopy = audio.sublist(0); // Make sure to copy before any awaits.
final dir = await directory();
final filename = '${_debugIndex}_${base64Url.encode(safCode)}.wav';
final path = '$dir/$filename';
print(
"C:/Users/tiusic/AppData/Local/Android/Sdk/platform-tools/adb.exe pull $path $filename");
final filename = "${_debugIndex}_${base64Url.encode(safCode)}.wav";
final path = "$dir/$filename";
_log.info(
"C:/Users/tiusic/AppData/Local/Android/Sdk/platform-tools/adb.exe pull "
"$path $filename");
await Wav([audioCopy], kSampleRate).writeFile(path);
}

Expand Down
39 changes: 17 additions & 22 deletions lib/defender.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:isolate';
import 'dart:typed_data';

import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:qr/qr.dart';

import 'const.dart';
import 'crypto.dart';
import 'debug_file.dart';
import 'metadata.dart';
import 'microphone.dart';
import 'pipeline.dart';
import 'saf_code_builder.dart';
import 'util.dart';
import "dart:isolate";
import "dart:typed_data";

import "package:flutter/services.dart";
import "package:qr/qr.dart";

import "const.dart";
import "crypto.dart";
import "debug_file.dart";
import "metadata.dart";
import "microphone.dart";
import "pipeline.dart";
import "saf_code_builder.dart";

/// Connects a Microphone to a SafCodeBuilder etc running in a separate Isolate.
///
Expand All @@ -42,20 +40,18 @@ class Defender {
final void Function(int, QrCode) _setQr;
final Future<PrivateKey> _privateKey;
final _recv = ReceivePort();
late final Future<Microphone?> _microphone;
late final Future<Isolate> _isolate;
SendPort? _send;

Defender(this._setQr, this._privateKey) {
_recv.listen(_onMessage);
final rootToken = RootIsolateToken.instance!;
_isolate = Isolate.spawn(defenderIsolateMain, [_recv.sendPort, rootToken]);
_microphone = Microphone.mic(_updateCode);
Isolate.spawn(defenderIsolateMain, [_recv.sendPort, rootToken]);
Microphone.mic(_updateCode);
}

void _onMessage(dynamic message) {
if (message is SendPort) {
_send = message as SendPort;
_send = message;
_privateKey.then((pk) => _send?.send(pk));
} else {
final qrm = message as QrMessage;
Expand Down Expand Up @@ -108,8 +104,7 @@ class DefenderIsolate {

void _onMessage(dynamic message) {
if (message is PrivateKey) {
_codeBuilder =
SafCodeBuilder(Metadata(), (message as PrivateKey).signer());
_codeBuilder = SafCodeBuilder(Metadata(), (message).signer());
} else {
final am = message as AudioMessage;
_pipeline.onData(am.timeMs, am.audio);
Expand Down
27 changes: 12 additions & 15 deletions lib/hasher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:typed_data';
import "dart:typed_data";

import 'package:fftea/fftea.dart';

import 'const.dart';
import 'util.dart';
import "util.dart";

// Receives a stream frequency buckets. Yields a stream of hashes.
//
Expand All @@ -33,7 +30,7 @@ class Hasher {
late final Uint32List _volume;
late final Uint64List _hashes;

final Float64List _prevPow_dF;
final Float64List _prevPowDF;
final Function(int, Float64List, Uint8List) _reportFingerprint;

static const kReset = -1;
Expand All @@ -43,7 +40,7 @@ class Hasher {

Hasher(int bitsPerHash, int hashesPerChunk, this._reportFingerprint)
: _size = 8 * hashesPerChunk + 4,
_prevPow_dF = Float64List(bitsPerHash) {
_prevPowDF = Float64List(bitsPerHash) {
// We want the _hashes array to be 8-byte aligned, even to the volume prefix
// is 4 bytes. So allocate an array with an additional 4 byte prefix.
final bufSize = _size + 4;
Expand All @@ -54,16 +51,16 @@ class Hasher {
}

void onData(Float64List powers) {
assert(powers.length == _prevPow_dF.length + 1);
assert(powers.length == _prevPowDF.length + 1);
int h = 0;
for (int i = 0; i < _prevPow_dF.length; ++i) {
final pow_dF = powers[i + 1] - powers[i];
for (int i = 0; i < _prevPowDF.length; ++i) {
final powDF = powers[i + 1] - powers[i];
if (_k >= 0) {
if (pow_dF - _prevPow_dF[i] > 0) {
if (powDF - _prevPowDF[i] > 0) {
h |= 1 << i;
}
}
_prevPow_dF[i] = pow_dF;
_prevPowDF[i] = powDF;
}
if (_k >= 0) {
_hashes[_k] = h;
Expand All @@ -78,7 +75,7 @@ class Hasher {
_k = kReset;
}

static const int U32MAX = (1 << 32) - 1;
static int volToU32(double volume) => (clamp(volume, 0, 1) * U32MAX).toInt();
static double u32ToVol(int u32) => u32.toDouble() / U32MAX;
static const int u32Max = (1 << 32) - 1;
static int volToU32(double volume) => (clamp(volume, 0, 1) * u32Max).toInt();
static double u32ToVol(int u32) => u32.toDouble() / u32Max;
}
8 changes: 3 additions & 5 deletions lib/key_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:convert';
import "package:flutter/foundation.dart";
import "package:shared_preferences/shared_preferences.dart";

import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'crypto.dart';
import "crypto.dart";

/// Provides an RSA public/private key pair.
///
Expand Down
Loading

0 comments on commit b3cac70

Please sign in to comment.