Open cloudseasail opened 3 years ago
Yes, same issue here. Additionally, on iOS it seems that idle dB level (when no sound is happening) is less than 1dB but on my android device it's close to 20dB. So, the dB range on Android is only around 44 dB in total.
I can work around this in my code by applying specific logic for each platform but it's definitely weird and would be a good fix if it's possible. It could be due to hardware differences but given that you have a completely different device than me (I'm testing with a OnePlus 6) it's more likely a software problem.
@Larpoux are there any active contributors to Tau currently?
For me most of the subscription issues (including this one, and the decibels dropping to 0) disappear when I record to a file instead of a stream.
@Larpoux are there any active contributors to Tau currently?
You are hitting the main great τ problem. I think that this package is very good and can be potentially THE flutter plugin to do sounds.
But actually no contributors. 👎 I work myself from time to time on this project but not full time. This project cannot live without contributors. The TODO tasks are impressive and need at least one or two developers full time.
For me most of the subscription issues (including this one, and the decibels dropping to 0) disappear when I record to a file instead of a stream.
I am not surprised by what you are saying. Recording to file and to buffers use the Operating System Media recorder. The DB level is obtained by the OS, and is certainly correct.
When I developed recording to streams, I tried to code something to get the DB level. My code is trivial and is probably completely bad. Both on iOS and Android. Someone should master what is PCM and code correctly how to get DB level from PCM.
For me most of the subscription issues (including this one, and the decibels dropping to 0) disappear when I record to a file instead of a stream.
Are you talking about record to a file and read decibels from files? Seems there is no such API availabe right now. If you mean record toFile, I am already using this in fact
void record() { _mRecorder! .startRecorder( toFile: _mPath, ) .then((value) { setState(() {}); }); _mRecorder!.onProgress!.listen((e) { print(e.decibels); _noiseLevel = e.decibels!.round().toString(); setState(() {}); }); }
Are you talking about record to a file and read decibels from files? Seems there is no such API availabe right now.
A long time ago, we had an issue from someone who wanted to do a static histogram of the dblevel of his/her record. Someone else posted a response that we can use FFmpeg to do that. I am not sure that his/her response was correct, but perhaps you could try to find this issue and look to it (I do not kown its number : issues are again a terrible mess).
This issue is stale because it has been open 90 days with no activity. Leave a comment or this will be closed in 7 days.
Is there any update progress? I used the e.decibels returned by Recorder.onProgress to draw the waveform, but the decibels seems to be inaccurate. @Larpoux
On the left are waveforms drawn by other app, and on the right are waveforms drawn by me. My waveform doesn't seem to fluctuate that much
flutter_sound: 9.9.2 Android13
Someone should master what is PCM and code correctly how to get DB level from PCM.
This remark was 3 years ago. But during these 3 years, nobody tried to work on that point. This is bad.
Note: if you use StartRecorderToStream, you receive the audio data in your StreamSink. You can compute yourself the db level of this stream, using the algorithm that is good for you (there are many algorithms possible. Several of them are pretty complex, and others are very simple). Perhaps some Flutter Sound users already did that and can give to you the correct code.
But of course it would be much better to insert this code inside Flutter Sound itself.
In may, we had a Pull Request for Flutter Web for the db recording level #1031.
Actually we have a problem because our 3 platforms (Android, iOS and Web) are never synchronized. Some features are supported better on web, others are supported better on iOS or Android. My wish is to merge android, iOS and web code inside a common code. Half of this code will be coded in dart, and the other half will be coded in rust and accessed via FFI.
This is a major dev, and I don’t expect to deliver a beta version of Flutter Sound 10.0 before next year.
Note: if you use StartRecorderToStream, you receive the audio data in your StreamSink. You can compute yourself the db level of this stream, using the algorithm that is good for you (there are many algorithms possible. Several of them are pretty complex, and others are very simple). Perhaps some Flutter Sound users already did that and can give to you the correct code.
But of course it would be much better to insert this code inside Flutter Sound itself.
Okay, then I'll try using the data stream returned by StreamSink to calculate decibels Thanks a lot.
@SheepYang1993 , I expect to work on this point soon. Probably in a few weeks. If you can wait a little bit, it will be certainly better than to implement yourself this feature.
Btw, can't startRecorder (toStreamInt16) be used now? I can't get the callback, in recorder.onProgress. but toStream can get the callback. flutter_sound: 9.9.2
@Larpoux
Actually, toStreamInt16 and toStreamFloat32 are only implemented on flutter web. Still not on mobiles. This is one of the many things that I have to do. This is important to support these two codecs, because it is actually the only way to work with several channels.
StreamController<Uint8List> recordingDataController = StreamController<Uint8List>();
recordingDataSubscription = recordingDataController.stream.listen((Uint8List buffer) {
sink.add(buffer);
voiceWaveList.addAll(buffer);
});
await soundRecorder.startRecorder(
toStream: recordingDataController.sink,
codec: Codec.pcm16,
numChannels: 1,
sampleRate: 44100,
bufferSize: 8192,
);
How can I obtain Int16List ? @Larpoux
You can try to get the ByteBuffer of your UInt8List and then get the int16List with asInt16List()
.
Note : I have never tried this.
Usually I loop into the UInt8List and build a Int16 from each two uint8. This is very simple.
But the former way should be more efficient.
Sorry,I just don't know how to splice two Uint8Lists into an Int16List now
I tried to splice it together like this, but the result was not correct
stream.listen((Uint8List buffer) {
sink.add(buffer);
tempList.add(buffer);
if (tempList.length >= 2) {
Int16List buffer16 = Int16List.fromList(tempList[0] + tempList[1]);
voiceWaveList.addAll(buffer16);
tempList.clear();
}
});
I can now draw the correct waveform using the following code
final ByteData data = await rootBundle.load('assets/sound/sample.pcm');
final Int16List bytes =
data.buffer.asInt16List(data.offsetInBytes, data.lengthInBytes ~/ 2);
voiceWaveList.addAll(bytes.toList());
@Larpoux
Yes, using the data buffer is probably better.
For your information :
Uint8List buf = Uint8List(2 * bufferInt16.length);
for (int i = 1; i < bufferInt16.length; ++i) {
int v = bufferInt16[i];
buf[2 * i + 1] = v >> 8; // Little Endian
buf[2 * i] = v & 0xFF;
}
And the opposite
Int16List buf = Int16List(bufferUint8List.length /2);
for (int i = 0; i < buf.length; ++ i)
{
buf[i] = bufferUint8List[2*i+1] * 256 + bufferUint8List[2*i]; // Little Endian
}
Note : this code is not tested and could be adjusted if necessary
Wondering how the decibels value was caculated, is it reflecting the real dB value range ? (from 0 to 120dB) Actually, I never see a value larger than 63dB in my test, no matter how loud the sound is. (my kid is trying his best to yell :D)
I tried to setSubscriptionDuration from 100ms to 500ms, it make no differnce. My device is Android Mi 8. flutter_sound: ^8.1.4