fighttech-vn / easy_audio

BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Coodinator record audio #1

Open trunghieuvn opened 1 year ago

trunghieuvn commented 1 year ago

usecasse 1: record audio trả ra item audio có thể play đc để nghe lại usecase 2: gắn cái cái audio to text :D

Future<T?> startRecord();

record xong trả a cái path của file audio local Button record này sẽ gọi cái buttomsheet em code lên để lấy đc file audio record

tạo cái example proejct rồi đẩy cái screen demo ra trước nha

image

trunghieuvn commented 1 year ago
import 'dart:math';

import 'package:flutter/material.dart';

import '../../../../../theme/theme_color.dart';

class FixedWaveform extends StatelessWidget {
  final List<double> templates;
  final Size size;
  final double waveThickness;

  const FixedWaveform({
    Key? key,
    this.templates = const [3.67, 11.8, 24, 15.87, 7.74, 15.87, 3.67],
    this.size = const Size(double.infinity, 24),
    this.waveThickness = 2.2,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ShaderMask(
      shaderCallback: (Rect bounds) {
        return const LinearGradient(
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
          colors: [
            Color(0xff5AA3F1),
            Color(0xff35C78B),
          ],
        ).createShader(bounds);
      },
      child: CustomPaint(
        size: size,
        painter: WavePainter(
          templates: templates,
          waveThickness: waveThickness,
          waveColor: Colors.white,
        ),
      ),
    );
  }
}

enum WaveForm { fit, contain }

class WavePainter extends CustomPainter {
  final List<double> templates;
  final double animValue;
  final Color? waveColor;
  final StrokeCap waveCap;
  final double waveThickness;
  final double waveSpace;
  final Shader? fixedWaveGradient;
  final WaveForm form;

  WavePainter({
    required this.templates,
    this.animValue = 0,
    this.waveSpace = 1.4,
    this.waveColor,
    this.waveCap = StrokeCap.round,
    this.waveThickness = 2.2,
    this.fixedWaveGradient,
    this.form = WaveForm.fit,
  }) : wavePaint = Paint()
          ..color = waveColor ?? themeColor.primaryColor
          ..strokeWidth = waveThickness
          ..strokeCap = waveCap
          ..shader = fixedWaveGradient;

  Paint wavePaint;

  @override
  void paint(Canvas canvas, Size size) {
    // print('$runtimeType $templates');
    _drawFixedWave(size, canvas);
  }

  @override
  bool shouldRepaint(WavePainter oldDelegate) => false;

  void _drawFixedWave(Size size, Canvas canvas) {
    final coupleWidth = waveThickness + waveSpace;
    final waveAndSpaceCount = (size.width - waveThickness) ~/ coupleWidth;
    final remainingWidth =
        (size.width - waveThickness) - (waveAndSpaceCount * coupleWidth);
    final start = remainingWidth / 2 + waveThickness / 2;
    final templateCount = templates.length;
    final maxT = templates.reduce(max);
    for (var i = 0; i <= waveAndSpaceCount; i++) {
      final t = templates[i % templateCount];
      double waveHeight;
      final _start = start + (coupleWidth * i);
      if (form == WaveForm.fit) {
        waveHeight = t / maxT * (size.height - waveThickness);
      } else {
        waveHeight = t - waveThickness;
      }
      canvas.drawLine(
        Offset(_start, size.height / 2 - waveHeight / 2),
        Offset(_start, size.height / 2 + waveHeight / 2),
        wavePaint,
      );
    }
  }
}

class AnimatedWaveform extends StatefulWidget {
  final List<double> templates;
  final bool playing;
  final WaveForm form;
  final double waveThickness;

  const AnimatedWaveform({
    Key? key,
    this.templates = const [
      3.67,
      15.87,
      7.74,
      3.67,
      7.74,
      15.87,
      3.67,
      2.4,
      15.87,
      3.67,
      15.87,
      15.87,
      7.74,
      3.67,
      4.4,
      3.67,
      2.4,
      3.67,
      2.4,
      3.67,
      2.4,
      7.74,
      3.67,
      2.4,
      7.74,
      2.4,
      3.67,
      2.4,
      3.67,
      3.67,
      2.4,
      7.74,
      3.67,
      2.4,
      7.74,
      2.4,
      3.67,
      2.4,
      3.67,
      3.67,
      2.4,
      7.74,
      2.4,
      3.67,
      2.4,
      3.67,
      3.67,
      2.4,
      7.74,
      2.4,
      2.4,
      11.8,
      40,
      15.87,
      7.74,
      3.67,
      7.74,
      15.87,
      3.67,
      2.4,
      15.87,
      3.67,
      15.87,
      7.74,
      3.67,
      2.4,
      15.87,
      7.74,
      3.67,
      3.67,
      3.67,
      2.4,
      3.67,
      2.4,
      7.74,
      3.67,
      2.4,
      3.67,
      2.4,
      3.67,
      7.74,
      3.67,
      2.4,
      3.67,
      7.74,
    ],
    this.playing = true,
    this.form = WaveForm.contain,
    this.waveThickness = 4,
  }) : super(key: key);

  @override
  State<AnimatedWaveform> createState() => _AnimatedWaveformState();
}

class _AnimatedWaveformState extends State<AnimatedWaveform>
    with SingleTickerProviderStateMixin {
  late final AnimationController controller;
  late final Animation<double> animation;

  AnimationStatus? last;

  @override
  void initState() {
    controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    )..addListener(() {
        if (controller.isCompleted) {
          last = AnimationStatus.reverse;
          controller.reverse();
        } else if (controller.isDismissed) {
          last = AnimationStatus.forward;
          controller.forward();
        }
      });
    if (widget.playing) {
      controller.forward();
    }
    animation = Tween(begin: 0.3, end: 0.7).animate(controller);
    super.initState();
  }

  @override
  void didUpdateWidget(covariant AnimatedWaveform oldWidget) {
    if (widget.playing) {
      if (last == null || last == AnimationStatus.forward) {
        controller.forward();
      } else {
        controller.reverse();
      }
    } else {
      controller.stop();
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final maxValue = widget.templates.reduce(max);

    return AnimatedBuilder(
      animation: animation,
      builder: (context, child) {
        return ShaderMask(
          shaderCallback: (Rect bounds) {
            return const LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              colors: [
                Color(0xff5AA3F1),
                Color(0xff35C78B),
              ],
            ).createShader(bounds);
          },
          child: CustomPaint(
            size: Size(
              double.infinity,
              maxValue,
            ),
            painter: WavePainter(
              templates: [
                ...widget.templates.asMap().entries.map((e) {
                  if (e.value < (maxValue / 2)) {
                    return e.value / animation.value;
                  } else {
                    return e.value * animation.value;
                  }
                }),
              ],
              waveThickness: widget.waveThickness,
              waveColor: Colors.white,
              form: widget.form,
            ),
          ),
        );
      },
    );
  }
}