Skip to content

Commit

Permalink
fix the resampling buffer crash and add con complexity and signal typ…
Browse files Browse the repository at this point in the history
…e options
  • Loading branch information
goatchurchprime committed Oct 31, 2024
1 parent 152feef commit b24bdbe
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 13 deletions.
6 changes: 2 additions & 4 deletions example/radiomqtt/radiomqtt.gd
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var audioresamplerate : int = 48000
var audioresamplesize : int = 960
var opussamplerate : int = 48000
var opusframesize : int = 960
var prefixbyteslength : int = 0
var prefixbytes = PackedByteArray([0,0,0,0,1])
var mqttpacketencodebase64 : bool = false

var recordedsamples = [ ]
Expand Down Expand Up @@ -156,11 +156,10 @@ func updatesamplerates():
$VBoxFrameLength/HBoxAudioFrame/LabResampleFrameLength.text = "%d samples" % audioresamplesize
recordedheader = { "opusframesize":audioresamplesize,
"opussamplerate":audioresamplerate,
"prefixbyteslength":prefixbyteslength,
"prefixbyteslength":len(prefixbytes),
"mqttpacketencoding":"base64" if mqttpacketencodebase64 else "binary" }
if len(recordedsamples) != 0 and len(recordedsamples[0]) != audiosamplesize:
recordedsamples = resamplerecordedsamples(recordedsamples, audiosamplesize)
var prefixbytes = PackedByteArray()
recordedopuspacketsMemSize = 0
recordedopuspackets = null
recordedresampledpackets = null
Expand Down Expand Up @@ -279,7 +278,6 @@ func _process(_delta):
endtalking()
$HBoxMicTalk/MicWorking.button_pressed = $AudioStreamMicrophone.playing

var prefixbytes = PackedByteArray()
if audioeffectcapture == null:
assert (audioopuschunkedeffect != null)
while audioopuschunkedeffect.chunk_available():
Expand Down
29 changes: 22 additions & 7 deletions src/audio_effect_opus_chunked.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ void AudioEffectOpusChunked::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_opusframesize"), &AudioEffectOpusChunked::get_opusframesize);
ClassDB::bind_method(D_METHOD("set_opusbitrate", "opusbitrate"), &AudioEffectOpusChunked::set_opusbitrate);
ClassDB::bind_method(D_METHOD("get_opusbitrate"), &AudioEffectOpusChunked::get_opusbitrate);
ClassDB::bind_method(D_METHOD("set_opuscomplexity", "opuscomplexity"), &AudioEffectOpusChunked::set_opuscomplexity);
ClassDB::bind_method(D_METHOD("get_opuscomplexity"), &AudioEffectOpusChunked::get_opuscomplexity);
ClassDB::bind_method(D_METHOD("set_opusoptimizeforvoice", "opusoptimizeforvoice"), &AudioEffectOpusChunked::set_opusoptimizeforvoice);
ClassDB::bind_method(D_METHOD("get_opusoptimizeforvoice"), &AudioEffectOpusChunked::get_opusoptimizeforvoice);
ClassDB::bind_method(D_METHOD("set_audiosamplerate", "audiosamplerate"), &AudioEffectOpusChunked::set_audiosamplerate);
ClassDB::bind_method(D_METHOD("get_audiosamplerate"), &AudioEffectOpusChunked::get_audiosamplerate);
ClassDB::bind_method(D_METHOD("set_audiosamplesize", "audiosamplesize"), &AudioEffectOpusChunked::set_audiosamplesize);
Expand All @@ -50,15 +54,14 @@ void AudioEffectOpusChunked::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_audiosamplechunks"), &AudioEffectOpusChunked::get_audiosamplechunks);

ADD_PROPERTY(PropertyInfo(Variant::INT, "opussamplerate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_opussamplerate", "get_opussamplerate");
ADD_PROPERTY(PropertyInfo(Variant::INT, "opusframesize", PROPERTY_HINT_RANGE, "20,2880,2"), "set_opusframesize", "get_opusframesize");
ADD_PROPERTY(PropertyInfo(Variant::INT, "opusbitrate", PROPERTY_HINT_RANGE, "3000,24000,1000"), "set_opusbitrate", "get_opusbitrate");

ADD_PROPERTY(PropertyInfo(Variant::INT, "opusframesize", PROPERTY_HINT_RANGE, "20,2880,1"), "set_opusframesize", "get_opusframesize");
ADD_PROPERTY(PropertyInfo(Variant::INT, "opusbitrate", PROPERTY_HINT_RANGE, "500,200000,1"), "set_opusbitrate", "get_opusbitrate");
ADD_PROPERTY(PropertyInfo(Variant::INT, "opuscomplexity", PROPERTY_HINT_RANGE, "0,10,1"), "set_opuscomplexity", "get_opuscomplexity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "opusoptimizeforvoice"), "set_opusoptimizeforvoice", "get_opusoptimizeforvoice");
ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplerate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_audiosamplerate", "get_audiosamplerate");
ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplesize", PROPERTY_HINT_RANGE, "10,4000,1"), "set_audiosamplesize", "get_audiosamplesize");
ADD_PROPERTY(PropertyInfo(Variant::INT, "audiosamplechunks", PROPERTY_HINT_RANGE, "1,200,1"), "set_audiosamplechunks", "get_audiosamplechunks");

// ClassDB::bind_method(D_METHOD("Dcreateencoder"), &AudioEffectOpusChunked::createencoder);

ClassDB::bind_method(D_METHOD("chunk_available"), &AudioEffectOpusChunked::chunk_available);
ClassDB::bind_method(D_METHOD("resampled_current_chunk"), &AudioEffectOpusChunked::resampled_current_chunk);
ClassDB::bind_method(D_METHOD("denoiser_available"), &AudioEffectOpusChunked::denoiser_available);
Expand Down Expand Up @@ -188,7 +191,19 @@ void AudioEffectOpusChunked::createencoder() {
}
int opuserror2 = opus_encoder_ctl(opusencoder, OPUS_SET_BITRATE(opusbitrate));
if (opuserror2 != 0) {
godot::UtilityFunctions::printerr("opus_encoder_ctl error error ", opuserror2);
godot::UtilityFunctions::printerr("opus_encoder_ctl bitrate error error ", opuserror2);
chunknumber = -2;
return;
}
int opuserror3 = opus_encoder_ctl(opusencoder, OPUS_SET_COMPLEXITY(complexity));
if (opuserror3 != 0) {
godot::UtilityFunctions::printerr("opus_encoder_ctl complexity error error ", opuserror3);
chunknumber = -2;
return;
}
int opuserror4 = opus_encoder_ctl(opusencoder, OPUS_SET_SIGNAL(signal_type));
if (opuserror4 != 0) {
godot::UtilityFunctions::printerr("opus_encoder_ctl signal_type error error ", opuserror4);
chunknumber = -2;
return;
}
Expand Down Expand Up @@ -329,7 +344,7 @@ PackedByteArray AudioEffectOpusChunked::read_opus_packet(const PackedByteArray&
}

void AudioEffectOpusChunked::flush_opus_encoder(bool denoise) {
if (opusframesize == 0)
if ((opusframesize == 0) || (chunknumber == -1))
return;
// this just sends 5 empty chunks into the encoder. doesn't necessarily work
float* paudioresamples = (float*)singleresamplebuffer.ptrw();
Expand Down
9 changes: 8 additions & 1 deletion src/audio_effect_opus_chunked.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "rnnoise_stub.h"
#endif


namespace godot {

class AudioEffectOpusChunked;
Expand Down Expand Up @@ -117,7 +118,9 @@ class AudioEffectOpusChunked : public AudioEffect {

int opussamplerate = 48000;
int opusframesize = 960;
int opusbitrate = 24000;
int opusbitrate = 12000;
int complexity = 5;
int signal_type = OPUS_SIGNAL_VOICE;

SpeexResamplerState* speexresampler = NULL;
PackedVector2Array audioresampledbuffer; // size opusframesize*ringbufferchunks
Expand Down Expand Up @@ -188,6 +191,10 @@ class AudioEffectOpusChunked : public AudioEffect {
int get_audiosamplesize() { return audiosamplesize; };
void set_audiosamplechunks(int laudiosamplechunks) { chunknumber = -1; ringbufferchunks = laudiosamplechunks; };
int get_audiosamplechunks() { return ringbufferchunks; };
void set_opuscomplexity(int lcomplexity) { chunknumber = -1; complexity = lcomplexity; };
int get_opuscomplexity() { return complexity; };
void set_opusoptimizeforvoice(bool loptimizeforvoice) { chunknumber = -1; signal_type = (loptimizeforvoice ? OPUS_SIGNAL_VOICE : OPUS_SIGNAL_MUSIC); };
bool get_opusoptimizeforvoice() { return (signal_type == OPUS_SIGNAL_VOICE); };

AudioEffectOpusChunked();
~AudioEffectOpusChunked();
Expand Down
7 changes: 6 additions & 1 deletion src/audio_stream_opus_chunked.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,18 @@ void AudioStreamOpusChunked::createdecoder() {
return;
}
}

float Dtimeframeopus = opusframesize*1.0F/opussamplerate;
float Dtimeframeaudio = audiosamplesize*1.0F/audiosamplerate;
if (audiosamplesize != opusframesize) {
int speexerror = 0;
int resamplingquality = 10;
speexresampler = speex_resampler_init(channels, opussamplerate, audiosamplerate, resamplingquality, &speexerror);
audiopreresampledbuffer.resize(opusframesize);
godot::UtilityFunctions::prints("Decoder timeframeopus preresampler", Dtimeframeopus, "timeframeaudio", Dtimeframeaudio);
} else {
godot::UtilityFunctions::prints("Decoder timeframeopus no-resampling needed", Dtimeframeopus, "timeframeaudio", Dtimeframeaudio);
}
audiopreresampledbuffer.resize(opusframesize);
Daudioresampledbuffer.resize(audiosamplesize);

audiosamplebuffer.resize(audiosamplesize*audiosamplechunks);
Expand Down Expand Up @@ -216,6 +217,10 @@ PackedVector2Array* AudioStreamOpusChunked::Popus_packet_to_chunk(const PackedBy
else
return &audiopreresampledbuffer;
}
if (audiopreresampledbuffer.size() != opusframesize) {
godot::UtilityFunctions::printerr("Errorrrr mismatch resampledaudio size");
return &audiopreresampledbuffer;
}
int decodedsamples = opus_decode_float(opusdecoder, opusbytepacket.ptr() + begin, opusbytepacket.size() - begin,
(float*)audiopreresampledbuffer.ptrw(), opusframesize, decode_fec);
if (audiosamplesize == opusframesize) {
Expand Down

0 comments on commit b24bdbe

Please sign in to comment.