Mix 8 bit audio files in flutter

155 Views Asked by At

I am trying to mix multiple WAV files into one using mixing algorithms I found in chatGPT answers and other websites.

I tried with simple step of mixing audio using the below code:

    double mixingRatio = 0.5;

    Uint8List? list = fileData1;
    for(int i = 0; i < fileData1.length; i++) {
      int mixedValue = ((1 - mixingRatio) * fileData1[i] + mixingRatio * fileData2[i]).round().clamp(0, 255);
      list[i] = mixedValue;
    }

    return list;
  }

There are too many clips and even though I am clamping (0-255). It still clips as seen in the picture. The input files are all normalized and confirmed from Audacity.

enter image description here

Looking for a mathematical solution to this simple problem. I don't want to use FFmpeg because it does not work with realtime data.

Thanks

EDIT:

This is how i am importing Raw Audio.

enter image description here

1

There are 1 best solutions below

2
Richard Heap On

In 8 bit unsigned PCM, the valid range is 0-255, with 128 as the 'zero' value. (Values above 128 are in the top half of the waveform and below 128 in the bottom half.)

Before you can perform maths (e.g. scaling, addition) on these values you need to normalise them. This is actually as simple as subtracting 128, so that you end up with an int in the range -128 to 127. You can now scale and add these values.

Of course, before storing the resulting, clamped (between -128 and 127) value back into an unsigned PCM byte array, you need to add back the bias value.

For example:

  final mixedValue = ((1 - mixingRatio) * (fileData1[i] - 128) +
              mixingRatio * (fileData2[i] - 128))
          .round()
          .clamp(-128, 127) +
      128;

By the way, you seem to be overwriting fileData1 with the result. This may not be what you intended. Double check this, because this may be your issue. The two formulae give different values. Try this:

void main() {
  print(oldWay(0.5, 113, 143)); // prints 113
  print(newWay(0.5, 113, 143)); // prints 128 (the correct value)
}

int oldWay(double r, int a, int b) {
  return ((1 - r) * a + r * a).round().clamp(0, 255);
}

int newWay(double r, int a, int b) {
  return ((1 - r) * (a - 128) + r * (b - 128)).round().clamp(-128, 127) + 128;
}