flutter_sound icon indicating copy to clipboard operation
flutter_sound copied to clipboard

[HELP]: decibels value never goes higher than 63, even the sound is very loud

Open cloudseasail opened this issue 4 years ago • 19 comments

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

cloudseasail avatar Jun 08 '21 11:06 cloudseasail

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?

mhstoller avatar Jun 19 '21 18:06 mhstoller

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.

maxkrieger avatar Aug 23 '21 00:08 maxkrieger

@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.

Larpoux avatar Aug 23 '21 16:08 Larpoux

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.

Larpoux avatar Aug 23 '21 16:08 Larpoux

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(() {}); }); }

cloudseasail avatar Sep 11 '21 12:09 cloudseasail

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).

Larpoux avatar Sep 11 '21 12:09 Larpoux

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.

github-actions[bot] avatar Dec 15 '23 01:12 github-actions[bot]

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 cf5352d2d990fecc4339382aa480111

flutter_sound: 9.9.2 Android13

SheepYang1993 avatar Aug 01 '24 09:08 SheepYang1993

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.

Larpoux avatar Aug 01 '24 16:08 Larpoux

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.

Larpoux avatar Aug 01 '24 17:08 Larpoux

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.

Larpoux avatar Aug 01 '24 18:08 Larpoux

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 avatar Aug 02 '24 01:08 SheepYang1993

@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.

Larpoux avatar Aug 02 '24 03:08 Larpoux

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

SheepYang1993 avatar Aug 02 '24 03:08 SheepYang1993

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.

Larpoux avatar Aug 02 '24 03:08 Larpoux

    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

SheepYang1993 avatar Aug 06 '24 07:08 SheepYang1993

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.

Larpoux avatar Aug 06 '24 07:08 Larpoux

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

SheepYang1993 avatar Aug 06 '24 09:08 SheepYang1993

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

Larpoux avatar Aug 06 '24 10:08 Larpoux