liamappelbe / wav

Dart package for reading and writing wav files
Apache License 2.0
18 stars 5 forks source link

[BUG] WAV is corrupted or not a WAV File? #6

Closed PcolBP closed 1 year ago

PcolBP commented 1 year ago

Hi, its me again :D

Thanks for package. Im not sure if its my side or your.

I'm recording voice by flutter_sound plugin and so my config looks like this:

SampleRate: 16000 Channels: 1 BitRate: 16000 Codec: PCM16

I can read later that file and display it but your package throws me error like below:

flutter: \^[[38;5;196m┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────<…>
flutter: \^[[38;5;196m│ \^[[0m\^[[39m\^[[48;5;196mFormatException: WAV is corrupted, or not a WAV file.<…>
flutter: \^[[38;5;196m├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄<…>
flutter: \^[[38;5;196m│ #0   TwLogger.e (package:tw_utils/logger/logger.dart:52:18)<…>
flutter: \^[[38;5;196m│ #1   main.<anonymous closure> (package:chat/main.dart:64:14)<…>
flutter: \^[[38;5;196m│ #2   _RootZone.runBinary (dart:async/zone.dart:1658:54)<…>
flutter: \^[[38;5;196m│ #3   runZonedGuarded.<anonymous closure> (dart:async/zone.dart:1800:18)<…>
flutter: \^[[38;5;196m│ #4   _Zone._processUncaughtError (dart:async/zone.dart:1073:14)<…>
flutter: \^[[38;5;196m│ #5   _CustomZone.handleUncaughtError (dart:async/zone.dart:1277:5)<…>
flutter: \^[[38;5;196m│ #6   Future._propagateToListeners (dart:async/future_impl.dart:680:16)<…>
flutter: \^[[38;5;196m│ #7   Future._completeError (dart:async/future_impl.dart:574:5)<…>
flutter: \^[[38;5;196m│ #8   _completeOnAsyncError (dart:async-patch/async_patch.dart:318:13)<…>
flutter: \^[[38;5;196m│ #9   _rootRunBinary (dart:async/zone.dart:1415:47)<…>
flutter: \^[[38;5;196m├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄<…>
flutter: \^[[38;5;196m│ ⛔ ***** Main runZonedGuarded() --> ErrorHandler<…>
flutter: \^[[38;5;196m└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────<…>

Link to example file recorded by flutter_sound uploaded to firestore - https://firebasestorage.googleapis.com/v0/b/tradewind-internal-f4761.appspot.com/o/voice_records%2Fvoice_2022-10-24T20%3A32%3A46.993797.wav?alt=media&token=e9891dc3-98b5-4592-9dfb-e112377dbae4

I would be grateful if you could tell me if that config is not supported or just my recorded files are corrupted. Thanks in advance!

EDIT 1:

We have found out that we should save files as pcm not wav. Do you know any way to achieve converting pcm to wav file?

liamappelbe commented 1 year ago

We have found out that we should save files as pcm not wav. Do you know any way to achieve converting pcm to wav file?

I'm not sure what a PCM file is, but if you have the samples in Dart, as an array of doubles, you can use package:wav to write them as a wav file. Just construct a Wav object, then write it to a file or a Uint8List.

PcolBP commented 1 year ago

Code below throws Infinity or NaN to Int in write method. Any thoughts?

final pcmBytes =
          Uint8List.fromList(state.soundRecord.bytes.reversed.toList());

      final wav = Wav(
        [pcmBytes.buffer.asFloat64List()],
        SoundConfig.BIT_RATE, // 16000
      );

      final wavBytes = wav.write();
gnudles commented 1 year ago

I think the exception is because you try to read the samples byte data as the actual wav file. But it is only an assumption

PcolBP commented 1 year ago

Ah, you may be right. Wav expecting to get bytes of actual wav file 🤔

liamappelbe commented 1 year ago

The Wav constructor is expecting a list of Float64List, where each element in the Float64List is a sample, typically from -1 to 1.

The bug in your code is that you're converting pcmBytes to a Float64List using asFloat64List, which just reinterprets each 8 byte chunk of the Uint8List as a double. This is probably not what you want to do.

What's the format of the sound that the recorder gives you? I think you mentioned it was 16 bit pcm. In that case you have to do asInt16List instead of asFloat64List, then manually convert the int samples to doubles.

If that's what you need, I have some functions inside Wav that do this. I could make them public. But let's try and confirm that this is your actual bug first.

gnudles commented 1 year ago

@liamappelbe Yeah you are right. It is much more reasonable. I am curious, why did you choose such large data type as f64 for audio samples? My implementation stores in i16 all the samples, and I think it is enough for most applications, and uses less space in memory.

liamappelbe commented 1 year ago

If you're doing audio analysis, or generating audio programatically, any math you do on the samples is going to be way easier if they're doubles. For example, I originally wrote the package because I was trying to test my FFT package by loading a wav file and FFTing it, which requires doubles.

gnudles commented 1 year ago

Oh I see.

PcolBP commented 1 year ago

Yep, i was able to read wave file. After correct adding wave header to pcm buffer. So it was my fault with file. Thanks anyway for your help and answers! image