i created a flutter app similar to clubhouse that provides rooms to have audio chats with users, now everything works as expected in the app and i am able to listen to audio when i send audio from mumble client to test but when i send audio from the microphone on my app, i hear a lot of distorted sounds on the client and other devices.
what could be the issue and what can i change in the code to avoid the distortion in the audio, i have tried with various frame times and input sample rates but it doesn't fix my issue
i am using the dumble package for flutter : /packages/dumble
Any suggestions will be helpful, Thanks!
const int inputSampleRate = 48000;
const int frameTimeMs = 40; // use frames of 40ms
const FrameTime frameTime = FrameTime.ms40;
const int outputSampleRate = 48000;
const int channels = 1;
int frameByteSize = (inputSampleRate ~/ 1000) * frameTimeMs * channels * 2;
// const int BUFFER_SIZE = 960 * 2; // 16-bit samples
class MumbleAPI {
late MumbleClient client;
bool _isConnected = false;
final String host = "SERVER_HOST_IP";
final int port = PORT_ADDRESS;
AudioFrameSink? _audioOutput;
late StreamOpusEncoder<int> encoder;
//// Connect to the Mumble Server
Future<void> connect({
required String username,
String password = '',
}) async {
try {
client = await MumbleClient.connect(
options: ConnectionOptions(
host: host,
port: port,
name: username,
context: await CertificateManager.getSecurityContext(),
),
onBadCertificate: (X509Certificate certificate) {
//Accept every certificate
return true;
});
MumbleExampleCallback callback = MumbleExampleCallback(client);
client.add(callback);
client.self.add(SelfCallback(client.self.session));
client.self.registerUser();
client.self.setSelfMute(mute: true);
client.audio.add(callback);
_isConnected = true;
encoder = StreamOpusEncoder.bytes(
frameTime: frameTime,
floatInput: false,
sampleRate: inputSampleRate,
channels: channels,
application: Application.voip);
_audioOutput = client.audio.sendAudio(codec: AudioCodec.opus);
/// Method - as documented in the the dumble package
/// .dart
/// instead of using the file to get data, i converted it to get stream from the
/// mic_stream and using it to yield the buffer and sending it.
microphoneAudioStream()
.transform(encoder)
.map((Uint8List audioBytes) => AudioFrame.outgoing(frame: audioBytes))
.pipe(_audioOutput!);
// Watch all users that are already on the server
// New users will reported to the callback and we will
// watch these new users in onUserAdded below
client.getUsers().values.forEach((User element) => element.add(callback));
print('Connected to the server as $username');
} catch (e) {
print('Failed to connect: $e');
rethrow;
}
}
Stream<List<int>> microphoneAudioStream() async* {
// Request permission to use the microphone
mic_stream.MicStream.shouldRequestPermission(true);
// Start capturing audio from the microphone with the specified sample rate and config
Stream<Uint8List>? micStream = mic_stream.MicStream.microphone(
audioSource: mic_stream.AudioSource.DEFAULT,
sampleRate: inputSampleRate,
channelConfig: mic_stream.ChannelConfig.CHANNEL_IN_MONO,
audioFormat: mic_stream.AudioFormat.ENCODING_PCM_16BIT,
);
if (micStream == null) {
throw Exception('Failed to initialize microphone stream.');
}
Uint8List? buffer;
int bufferIndex = 0;
await for (Uint8List data in micStream) {
int consumed = 0;
while (consumed < data.length) {
if (buffer == null && frameByteSize <= (data.length - consumed)) {
yield data.buffer.asUint8List(consumed, frameByteSize);
consumed += frameByteSize;
} else if (buffer == null) {
buffer = Uint8List(frameByteSize);
bufferIndex = 0;
} else {
int read = min(frameByteSize - bufferIndex, data.length - consumed);
buffer.setRange(bufferIndex, bufferIndex + read, data, consumed);
consumed += read;
bufferIndex += read;
if (bufferIndex == frameByteSize) {
yield buffer;
buffer = null;
}
}
}
} // Send remaining buffer if exists
if (buffer != null && bufferIndex > 0) {
yield buffer.sublist(0, bufferIndex);
}
}
I have tried using the frame time of 10ms, 20ms, 40ms, but it did not succeed, i have also used input sample rate of 8000 and 48000, but again the distorted audio did not fix.