Skip to content

Commit

Permalink
🔨 Fixed player button not showing up and made bitrate nullable and up…
Browse files Browse the repository at this point in the history
…date default recording extension to m4a (#140)

Co-authored-by: ujas-m-simformsolutions <[email protected]>
  • Loading branch information
ujas-m-simformsolutions and Ujas-Majithiya authored Dec 20, 2022
1 parent 685cd80 commit 8e276f9
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- **BREAKING**: Replaced `normalizationFactor` with `scaleFactor`and with this fixed [#43](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/43)
- Updated default values for bitRate and sampleRate
- Encoders, sample rate and bit rate can now Directly be set from `record` function.
- Bitrate is now nullable and default audio extension is now `m4a`.
- Updated example app

## 0.1.5+1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,23 @@ class AudioRecorder : PluginRegistry.RequestPermissionsResultListener {
result.success(recorder?.maxAmplitude?.toDouble() ?: 0.0)
}

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
fun initRecorder(
path: String,
result: MethodChannel.Result,
recorder: MediaRecorder?,
encoder: Int,
outputFormat: Int,
sampleRate: Int,
bitRate: Int
bitRate: Int?
) {
recorder?.apply {
setAudioSource(MediaRecorder.AudioSource.MIC)
setOutputFormat(getOutputFormat(outputFormat))
setAudioEncoder(getEncoder(encoder))
setAudioSamplingRate(sampleRate)
setAudioEncodingBitRate(bitRate)
if (bitRate != null) {
setAudioEncodingBitRate(bitRate)
}
setOutputFile(path)
try {
recorder.prepare()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
private var path: String? = null
private var encoder: Int = 0
private var outputFormat: Int = 0
private var sampleRate: Int = 16000
private var bitRate: Int = 64000
private var sampleRate: Int = 44100
private var bitRate: Int? = null
private lateinit var applicationContext: Context

//Todo: bitrate
Expand All @@ -51,8 +51,8 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
path = call.argument(Constants.path) as String?
encoder = (call.argument(Constants.encoder) as Int?) ?: 0
outputFormat = (call.argument(Constants.outputFormat) as Int?) ?: 0
sampleRate = (call.argument(Constants.sampleRate) as Int?) ?: 16000
bitRate = (call.argument(Constants.bitRate) as Int?) ?: 64000
sampleRate = (call.argument(Constants.sampleRate) as Int?) ?: 44100
bitRate = (call.argument(Constants.bitRate) as Int?)
checkPathAndInitialiseRecorder(result, encoder, outputFormat, sampleRate, bitRate)
}
Constants.startRecording -> audioRecorder.startRecorder(result, recorder)
Expand Down Expand Up @@ -160,13 +160,12 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
}
}

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private fun checkPathAndInitialiseRecorder(
result: Result,
encoder: Int,
outputFormat: Int,
sampleRate: Int,
bitRate: Int
bitRate: Int?
) {
try {
recorder = MediaRecorder()
Expand All @@ -179,7 +178,7 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
val dateTimeInstance = SimpleDateFormat(Constants.fileNameFormat, Locale.US)
val currentDate = dateTimeInstance.format(Date())
try {
outputFile = File.createTempFile(currentDate, ".aac", outputDir)
outputFile = File.createTempFile(currentDate, ".m4a", outputDir)
path = outputFile.path
audioRecorder.initRecorder(
path!!,
Expand Down
2 changes: 1 addition & 1 deletion example/lib/chat_bubble.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class _WaveBubbleState extends State<WaveBubble> {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (controller.playerState.isStopped)
if (!controller.playerState.isStopped)
IconButton(
onPressed: () async {
controller.playerState.isPlaying
Expand Down
40 changes: 23 additions & 17 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class _HomeState extends State<Home> with WidgetsBindingObserver {

void _getDir() async {
appDirectory = await getApplicationDocumentsDirectory();
path = "${appDirectory.path}/recording.mp3";
path = "${appDirectory.path}/recording.m4a";
isLoading = false;
setState(() {});
}
Expand All @@ -57,8 +57,7 @@ class _HomeState extends State<Home> with WidgetsBindingObserver {
..androidEncoder = AndroidEncoder.aac
..androidOutputFormat = AndroidOutputFormat.mpeg4
..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
..sampleRate = 44100
..bitRate = 48000;
..sampleRate = 44100;
}

void _pickFile() async {
Expand Down Expand Up @@ -114,7 +113,8 @@ class _HomeState extends State<Home> with WidgetsBindingObserver {
index: index + 1,
isSender: index.isOdd,
width: MediaQuery.of(context).size.width / 2,
isLastWidget: !isRecordingCompleted || musicFile == null,
isLastWidget:
!isRecordingCompleted || musicFile == null,
appDirectory: appDirectory,
);
},
Expand Down Expand Up @@ -212,21 +212,27 @@ class _HomeState extends State<Home> with WidgetsBindingObserver {
}

void _startOrStopRecording() async {
if (isRecording) {
recorderController.reset();
final path = await recorderController.stop(false);

if (path != null) {
isRecordingCompleted = true;
debugPrint("Recorded file size: ${File(path).lengthSync()}");
debugPrint(path);
try {
if (isRecording) {
recorderController.reset();

final path = await recorderController.stop(false);

if (path != null) {
isRecordingCompleted = true;
debugPrint("Recorded file size: ${File(path).lengthSync()}");
debugPrint(path);
}
} else {
await recorderController.record();
}
} else {
await recorderController.record(path: path);
} catch (e) {
debugPrint(e.toString());
} finally {
setState(() {
isRecording = !isRecording;
});
}
setState(() {
isRecording = !isRecording;
});
}

void _refreshWave() {
Expand Down
13 changes: 10 additions & 3 deletions ios/Classes/AudioRecorder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,26 @@ public class AudioRecorder: NSObject, AVAudioRecorderDelegate{

public func startRecording(_ result: @escaping FlutterResult,_ path: String?,_ encoder : Int?,_ sampleRate : Int?,_ bitRate : Int?,_ fileNameFormat: String){
let settings = [
AVEncoderBitRateKey: bitRate ?? 48000,
AVFormatIDKey: getEncoder(encoder ?? 0),
AVSampleRateKey: sampleRate ?? 44100,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
let settingsWithBitrate = [
AVEncoderBitRateKey: bitRate,
AVFormatIDKey: getEncoder(encoder ?? 0),
AVSampleRateKey: sampleRate ?? 44100,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]

let options: AVAudioSession.CategoryOptions = [.defaultToSpeaker, .allowBluetooth]
if (path == nil) {
let directory = NSTemporaryDirectory()
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = fileNameFormat
let fileName = dateFormatter.string(from: date) + ".aac"
let fileName = dateFormatter.string(from: date) + ".m4a"

self.path = NSURL.fileURL(withPathComponents: [directory, fileName])?.absoluteString
} else {
Expand All @@ -34,7 +41,7 @@ public class AudioRecorder: NSObject, AVAudioRecorderDelegate{
try AVAudioSession.sharedInstance().setActive(true)

let url = URL(string: self.path!) ?? URL(fileURLWithPath: self.path!)
audioRecorder = try AVAudioRecorder(url: url, settings: settings)
audioRecorder = try AVAudioRecorder(url: url, settings: bitRate != nil ? settingsWithBitrate as [String : Any] : settings as [String : Any])
audioRecorder?.delegate = self
audioRecorder?.isMeteringEnabled = true
audioRecorder?.record()
Expand Down
4 changes: 2 additions & 2 deletions lib/src/base/audio_waveforms_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class AudioWaveformsInterface {
Future<bool> record({
required int audioFormat,
required int sampleRate,
required int bitRate,
int? bitRate,
String? path,
}) async {
final isRecording = await _methodChannel.invokeMethod(
Expand All @@ -35,7 +35,7 @@ class AudioWaveformsInterface {
required int encoder,
required int outputFormat,
required int sampleRate,
required int bitRate,
int? bitRate,
}) async {
final initialized = await _methodChannel.invokeMethod(
Constants.initRecorder,
Expand Down
15 changes: 13 additions & 2 deletions lib/src/controllers/recorder_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ class RecorderController extends ChangeNotifier {

int sampleRate = 44100;

int bitRate = 48000;
int? bitRate;

/// Current maximum peak power for ios and peak amplitude android.
double _maxPeak = Platform.isIOS ? 1 : 32786.0;

/// Current min value.
double _currentMin = 0;

/// Current list of scaled waves. For IOS, this list contains normalised
/// peak power and for Android, this list contains normalised peak
/// amplitude.
Expand Down Expand Up @@ -279,7 +282,15 @@ class RecorderController extends ChangeNotifier {
void _normalise(double peak) {
final absDb = peak.abs();
_maxPeak = max(absDb, _maxPeak);
final scaledWave = (absDb / _maxPeak);

// calculates min value
_currentMin = _waveData.fold(
0,
(previousValue, element) =>
element < previousValue ? element : previousValue,
);

final scaledWave = (absDb - _currentMin) / (_maxPeak - _currentMin);
_waveData.add(scaledWave);
notifyListeners();
}
Expand Down

0 comments on commit 8e276f9

Please sign in to comment.