flutter_pitch_detection 1.3.1 copy "flutter_pitch_detection: ^1.3.1" to clipboard
flutter_pitch_detection: ^1.3.1 copied to clipboard

A Flutter plugin for real-time audio pitch detection using TarsosDSP on Android. Provides frequency, note, octave, volume, and accuracy measurements.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:flutter_pitch_detection/flutter_pitch_detection.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final pitchDetector = FlutterPitchDetection();
  StreamSubscription<Map<String, dynamic>>? _pitchSubscription;

  static const defaultSampleRate = 44100;
  static const defaultTolerance = 0.6;
  static const defaultPrecision = 0.8;
  static const defaultBufferSize = 8196;
  static const defaultA4Reference = 440.0;

  String note = "";
  int midiNote = 0;
  double frequency = 0;
  String noteOctave = "";
  int octave = 0;
  double toleranceCents = defaultTolerance;
  int bufferSize = defaultBufferSize;
  int sampleRate = defaultSampleRate;
  bool isRecording = false;
  bool isOnPitch = false;
  int accuracy = 0;
  double minPrecision = defaultPrecision;
  double volume = 0;
  double volumeDbFS = 0;
  Uint8List? pcmData;
  List<double>? streamData;
  double pitchDeviation = 0;
  double a4Reference = defaultA4Reference;

  @override
  void initState() {
    super.initState();
  }

  void onStartPressed() async {
    if (!isRecording) {
      try {
        await pitchDetector.startDetection();

        bool rec = await pitchDetector.isRecording();
        setState(() {
          isRecording = rec;
        });
        debugPrint("[START] Is Recording: $isRecording");

        pitchDetector.setParameters(
          toleranceCents: defaultTolerance,
          bufferSize: defaultBufferSize,
          sampleRate: defaultSampleRate,
          minPrecision: defaultPrecision,
          a4Reference: defaultA4Reference,
        );

        _pitchSubscription = pitchDetector.onPitchDetected.listen((data) async {
          final stream = await pitchDetector.getRawDataFromStream();
          final pcm = await pitchDetector.getRawPcmDataFromStream();

          setState(() {
            noteOctave = data['noteOctave'] ?? "";
            note = data['note'] ?? "";
            octave = data['octave'] ?? 0;
            midiNote = data['midiNote'] ?? 0;
            frequency = data['frequency'] ?? 0;

            accuracy = data['accuracy'] ?? 0;
            pitchDeviation = data['pitchDeviation'] ?? 0;
            isOnPitch = data['isOnPitch'] ?? false;
            volume = data['volume'] ?? 0;
            volumeDbFS = data['volumeDbFS'] ?? 0;

            toleranceCents = data['toleranceCents'] ?? defaultTolerance;
            bufferSize = data['bufferSize'] ?? defaultBufferSize;
            sampleRate = data['sampleRate'] ?? defaultSampleRate;
            minPrecision = data['minPrecision'] ?? defaultPrecision;
            minPrecision = data['minPrecision'] ?? defaultPrecision;
            a4Reference = data['a4Reference'] ?? defaultA4Reference;

            streamData = stream;
            // debugPrint("RAW DATA: $streamData");

            pcmData = pcm;
            // debugPrint("PCM DATA: $pcmData");
          });
        });
      } catch (e) {
        debugPrint("Start Recording Error: $e");
      }
    }
  }

  void onStopPressed() async {
    if (isRecording) {
      try {
        await _pitchSubscription?.cancel();
        _pitchSubscription = null;

        await pitchDetector.stopDetection();
        setState(() {
          isRecording = false;
        });

        debugPrint("[STOP] Is Recording: $isRecording");
        resetValues();
      } catch (e) {
        debugPrint("Stop Recording Error: $e");
      }
    }
  }

  void resetValues() {
    setState(() {
      note = "";
      midiNote = 0;
      frequency = 0;
      noteOctave = "";
      octave = 0;

      toleranceCents = defaultTolerance;
      bufferSize = defaultBufferSize;
      sampleRate = defaultSampleRate;
      minPrecision = defaultPrecision;
      a4Reference = defaultA4Reference;

      isRecording = false;
      accuracy = 0;
      pitchDeviation = 0;
      isOnPitch = false;
      volume = 0;
      volumeDbFS = 0;

      pcmData = null;
      streamData = null;
    });
  }

  Widget _startButton(Size size) {
    return SizedBox(
      height: size.height * 0.1,
      width: size.width * 0.1,
      child: IconButton(
        onPressed: onStartPressed,
        icon: Icon(Icons.play_arrow_rounded, color: Colors.black),
      ),
    );
  }

  Widget _stopButton(Size size) {
    return SizedBox(
      height: size.height * 0.1,
      width: size.width * 0.1,
      child: IconButton(
        onPressed: onStopPressed,
        icon: Icon(Icons.stop_rounded, color: Colors.black),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Pitch Detection')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              //SizedBox(height: size.height * 0.3),
              Text("Pitch: $noteOctave", style: TextStyle(fontSize: 20)),
              Text("Note: $note", style: TextStyle(fontSize: 18)),
              Text("Octave: $octave", style: TextStyle(fontSize: 18)),
              Text("Midi Note: $midiNote", style: TextStyle(fontSize: 18)),
              Text(
                "Frequency: ${frequency.toStringAsFixed(2)} Hz",
                style: TextStyle(fontSize: 18),
              ),
              SizedBox(height: size.height * 0.02),
              Text("Accuracy: $accuracy%", style: TextStyle(fontSize: 18)),
              Text(
                "Pitch Deviation: $pitchDeviation",
                style: TextStyle(fontSize: 18),
              ),
              Text(
                "Volume: ${volume.toStringAsFixed(2)}",
                style: TextStyle(fontSize: 18),
              ),
              Text(
                "Volume from DbSF: ${volumeDbFS.toStringAsFixed(2)}",
                style: TextStyle(fontSize: 18),
              ),
              SizedBox(height: size.height * 0.02),
              Text(
                "Tolerance: ${toleranceCents.toStringAsFixed(2)}",
                style: TextStyle(fontSize: 18),
              ),
              Text(
                "Min Precision: ${minPrecision.toStringAsFixed(2)}",
                style: TextStyle(fontSize: 18),
              ),
              Text("BufferSize: $bufferSize", style: TextStyle(fontSize: 16)),
              Text("SampleRate: $sampleRate", style: TextStyle(fontSize: 16)),
              Text(
                "A4 Reference: $a4Reference",
                style: TextStyle(fontSize: 16),
              ),
              SizedBox(height: size.height * 0.02),
              Text("IsRecording: $isRecording", style: TextStyle(fontSize: 16)),
              Text(
                "OnPitch",
                style: TextStyle(
                  fontSize: 20,
                  color: isOnPitch ? Colors.green : Colors.transparent,
                ),
              ),
              SizedBox(height: size.height * 0.01),
              isRecording ? _stopButton(size) : _startButton(size),
            ],
          ),
        ),
      ),
    );
  }
}
1
likes
160
points
96
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for real-time audio pitch detection using TarsosDSP on Android. Provides frequency, note, octave, volume, and accuracy measurements.

Repository (GitHub)
View/report issues

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on flutter_pitch_detection