sound_recording 0.0.1 copy "sound_recording: ^0.0.1" to clipboard
sound_recording: ^0.0.1 copied to clipboard

Flutter sound recording plugin for DSP purposes, now supports android.

example/lib/main.dart

import 'dart:async';
import 'dart:isolate';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:scidart/numdart.dart';
import 'package:sound_recording/sound_recording.dart';
import 'package:scidart/scidart.dart';

late SendPort sendPort;
final streamController = StreamController<RecordingData>();

class RecordingData {
  final List<int> items;
  final List<double> spectrum;

  const RecordingData(this.items, this.spectrum);
}

void main() {
  final receivePort = ReceivePort();
  receivePort.listen((message) {
    if (message is SendPort) {
      sendPort = message;
      SoundRecording.onData(sendPort.send);
    } else {
      streamController.sink.add(message);
    }
  });
  Isolate.spawn(processRecordingData, receivePort.sendPort);
  runApp(const App());
}

class App extends StatefulWidget {
  const App({super.key});

  @override
  State<App> createState() => _AppState();
}

Future<void> processRecordingData(SendPort sendPort) async {
  final receivePort = ReceivePort();
  receivePort.listen((data) {
    final items = (data as List).cast<int>().map((i) => i.toDouble()).toList();
    final spectrum = rfft(Array(items));
    sendPort.send(RecordingData(data.cast<int>(),
        spectrum.sublist(0, spectrum.length ~/ 2).map(complexAbs).toList()));
  });
  sendPort.send(receivePort.sendPort);
}

class _AppState extends State<App> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.light(useMaterial3: true),
      darkTheme: ThemeData.dark(useMaterial3: true),
      home: WillPopScope(
        onWillPop: () async {
          await SoundRecording.stop();
          return true;
        },
        child: Scaffold(
          appBar: AppBar(
            toolbarHeight: 0,
            backgroundColor: Theme.of(context).scaffoldBackgroundColor,
          ),
          body: Column(children: [
            const SizedBox(height: 16),
            Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
              ElevatedButton(
                onPressed: () async {
                  if (await Permission.microphone.request().isGranted) {
                    SoundRecording.start(sampleRate: 8000, bufferSize: 1024);
                  }
                },
                child: const Text('START'),
              ),
              const ElevatedButton(
                onPressed: SoundRecording.stop,
                child: Text('STOP'),
              ),
            ]),
            const SizedBox(height: 16),
            Expanded(
              child: StreamBuilder(
                stream: streamController.stream,
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Waveform(snapshot.data!);
                  }
                  return const SizedBox();
                },
              ),
            ),
          ]),
        ),
      ),
    );
  }
}

class Waveform extends StatelessWidget {
  final RecordingData data;

  const Waveform(this.data, {super.key});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: CustomPaint(painter: WaveformPainter(data)),
    );
  }
}

class WaveformPainter extends CustomPainter {
  final RecordingData data;

  WaveformPainter(this.data);

  @override
  void paint(Canvas canvas, Size size) {
    paintSpectrum(canvas, size);
    paintWaveForm(canvas, size);
  }

  void paintSpectrum(Canvas canvas, Size size) {
    final slice = size.width / (data.spectrum.length - 1);
    var x = 0.0;
    for (final i in data.spectrum) {
      final y = (i / 262144) * size.height;
      final hslColor = HSLColor.fromAHSL(
          1, data.spectrum.indexOf(i) * 360 / data.spectrum.length, 1, 0.5);
      canvas.drawRect(
        Rect.fromLTWH(x, size.height - y, slice, y),
        Paint()..color = hslColor.toColor(),
      );
      x += slice;
    }
  }

  void paintWaveForm(Canvas canvas, Size size) {
    final slice = size.width / (data.items.length - 1);
    var x = 0.0;
    final points = data.items.map((i) {
      final y = (0.5 + i / 32768) * size.height;
      final offset = Offset(x, y);
      x += slice;
      return offset;
    });
    canvas.drawPoints(
      PointMode.lines,
      points.toList(),
      Paint()
        ..strokeWidth = 1
        ..color = Colors.grey,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
0
likes
140
pub points
14%
popularity

Publisher

unverified uploader

Flutter sound recording plugin for DSP purposes, now supports android.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on sound_recording