flutter_pitch_detection 1.1.3 copy "flutter_pitch_detection: ^1.1.3" to clipboard
flutter_pitch_detection: ^1.1.3 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;

  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;

  @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);

        _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;
            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;

            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;

      isRecording = false;
      accuracy = 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("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)),
              SizedBox(height: size.height * 0.02),
              Text("IsRecording: $isRecording", style: TextStyle(fontSize: 16)),
              //Text("OnPitch", style: TextStyle(fontSize: 16, color: accuracy > minPrecision ? Colors.green : Colors.transparent)),
              Text("OnPitch", style: TextStyle(fontSize: 20, color: isOnPitch ? Colors.green : Colors.transparent)),
              SizedBox(height: size.height * 0.01),
              isRecording ? _stopButton(size) : _startButton(size),
            ],
          ),
        ),
      ),
    );
  }
}
4
likes
0
points
71
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

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on flutter_pitch_detection

Packages that implement flutter_pitch_detection