void main_loop(void *connptr, MumbleClient::MumbleClientLib* mcl) { struct _conninfo *conninfo; _v3_net_message *msg; v3_event *ev; conninfo = connptr; if (debug >= 2) { v3_debuglevel(V3_DEBUG_PACKET | V3_DEBUG_PACKET_PARSE | V3_DEBUG_INFO); } if (! v3_login(conninfo->server, conninfo->username, conninfo->password, "")) { fprintf(stderr, "could not log in to ventrilo server: %s\n", _v3_error(NULL)); } while (keep_running) { // Handle the Mumble Client mcl->Pump(); // Handle incoming events msg = _v3_recv(V3_NONBLOCK); if ( msg != NULL ) { switch (_v3_process_message(msg)) { case V3_MALFORMED: _v3_debug(V3_DEBUG_INFO, "received malformed packet"); break; case V3_NOTIMPL: _v3_debug(V3_DEBUG_INFO, "packet type not implemented"); break; case V3_OK: _v3_debug(V3_DEBUG_INFO, "packet processed"); break; } // free(msg); // Looks like process_message handles freeing the memory used } // Handle any outgoing Events ev = v3_get_event(V3_NONBLOCK); if ( ev != NULL ) { if (debug) { fprintf(stderr, "vumble: got event type %d\n", ev->type); } switch (ev->type) { case V3_EVENT_DISCONNECT: keep_running = false; break; case V3_EVENT_LOGIN_COMPLETE: v3_change_channel(atoi(conninfo->channelid), ""); fprintf(stderr, "***********************************************************************************\n"); fprintf(stderr, "Connected to Ventrilo Server\n"); fprintf(stderr, "***********************************************************************************\n"); v3_serverprop_open(); break; } free(ev); } } }
void _v3_audio_amplify(v3_handle v3h, int16_t *pcm, uint32_t pcmlen, float **volume, size_t count) { static const int16_t samplemax = 0x7fff; static const int16_t samplemin = 0x7fff + 1; register float tmpsample; size_t pos; float mult; uint32_t ctr; _v3_enter(v3h, __func__); for (pos = 0; pos < count; ++pos) { if (volume[pos] && *volume[pos] >= 0.0 && *volume[pos] != 1.0) { mult = tan((*volume[pos] > 1.95 ? 1.95 : *volume[pos]) * M_PI * 25 / 100.0); _v3_debug(v3h, V3_DBG_INFO, "amplifying pcm to %.0f%% (multiplier: %f)", *volume[pos] * 100.0, mult); for (ctr = 0; ctr < pcmlen / sizeof(*pcm); ++ctr) { tmpsample = pcm[ctr]; tmpsample *= mult; pcm[ctr] = (tmpsample > samplemax) ? samplemax : (tmpsample < samplemin ? samplemin : tmpsample); } } } _v3_leave(v3h, __func__); }
void _v3_coder_destroy(v3_handle v3h, v3_coder *coder) { _v3_enter(v3h, __func__); if (coder->state) { _v3_debug(v3h, V3_DBG_MEMORY, "releasing %scoder state", (coder->encoder) ? "en" : "de"); switch (coder->index) { #ifdef HAVE_GSM case 0: gsm_destroy(coder->state); _v3_debug(v3h, V3_DBG_MEMORY, "released gsm state"); break; #endif #ifdef HAVE_OPUS case 1: case 2: if (coder->encoder) { opus_encoder_destroy(coder->state); } else { opus_decoder_destroy(coder->state); } _v3_debug(v3h, V3_DBG_MEMORY, "released opus state"); break; #endif #ifdef HAVE_SPEEX case 3: if (coder->encoder) { speex_encoder_destroy(coder->state); } else { speex_decoder_destroy(coder->state); } _v3_debug(v3h, V3_DBG_MEMORY, "released speex state"); break; #endif default: break; } coder->state = NULL; } _v3_leave(v3h, __func__); }
int _v3_audio_decode( v3_handle v3h, /* payload input */ int16_t index, int16_t format, v3_coder *coder, const uint8_t *data, int32_t datalen, /* pcm output */ uint8_t *pcm, uint32_t *pcmlen, /* optional args */ uint32_t *rate, uint8_t *channels) { uint32_t maxpcmlen; int ret = V3_OK; _v3_enter(v3h, __func__); if (!coder || !data || !datalen || !pcm || !pcmlen || (pcmlen && !*pcmlen)) { _v3_leave(v3h, __func__); return V3_FAILURE; } maxpcmlen = *pcmlen; *pcmlen = 0; if (channels) { *channels = 1; } if (coder->state && (coder->index != index || coder->format != format)) { _v3_coder_destroy(v3h, coder); } switch (index) { #ifdef HAVE_GSM case 0: { const v3_codec *codec = v3_codec_get(index, format); int opt = 1; _v3_debug(v3h, V3_DBG_INFO, "decoding %i bytes of gsm to pcm @ %u", datalen, codec->rate); if (!coder->state) { if (!(coder->state = gsm_create())) { _v3_debug(v3h, V3_DBG_INFO, "failed to create gsm decoder"); ret = V3_FAILURE; break; } _v3_debug(v3h, V3_DBG_MEMORY, "initialized gsm decoder state"); gsm_option(coder->state, GSM_OPT_WAV49, &opt); coder->index = index; coder->format = format; coder->encoder = false; } while ((datalen -= 65) >= 0 && *pcmlen + codec->framesize <= maxpcmlen) { if (gsm_decode(coder->state, (void *)data, (void *)pcm) || gsm_decode(coder->state, (void *)data+33, (void *)pcm+(codec->framesize/2))) { _v3_debug(v3h, V3_DBG_INFO, "failed to decode gsm packet"); } data += 65; pcm += codec->framesize; *pcmlen += codec->framesize; } if (rate) { *rate = codec->rate; } } break; #endif #ifdef HAVE_OPUS case 1: case 2: { const v3_codec *codec = v3_codec_get(index, format); int tmp; _v3_debug(v3h, V3_DBG_INFO, "decoding %i bytes of opus to pcm @ %u", datalen, codec->rate); if (!coder->state) { if (!(coder->state = opus_decoder_create(codec->rate, 2, &tmp))) { _v3_debug(v3h, V3_DBG_INFO, "failed to create opus decoder: %s", opus_strerror(tmp)); ret = V3_FAILURE; break; } _v3_debug(v3h, V3_DBG_MEMORY, "initialized opus decoder state"); coder->index = index; coder->format = format; coder->encoder = false; } if ((tmp = opus_decode(coder->state, data, datalen, (void *)pcm, maxpcmlen / sizeof(int16_t), 0)) <= 0) { _v3_debug(v3h, V3_DBG_INFO, "failed to decode opus packet"); } *pcmlen += tmp * sizeof(int16_t) * 2; if (rate) { *rate = codec->rate; } if (channels) { *channels = 2; } } break; #endif #ifdef HAVE_SPEEX case 3: { const v3_codec *codec = v3_codec_get(index, format); uint16_t framesize; SpeexBits bits; _v3_debug(v3h, V3_DBG_INFO, "decoding %i bytes of speex to pcm @ %u", datalen, codec->rate); if (!coder->state) { switch (codec->rate) { case 8000: coder->state = speex_decoder_init(&speex_nb_mode); break; case 16000: coder->state = speex_decoder_init(&speex_wb_mode); break; case 32000: coder->state = speex_decoder_init(&speex_uwb_mode); break; } if (!coder->state) { _v3_debug(v3h, V3_DBG_INFO, "failed to create speex decoder"); ret = V3_FAILURE; break; } _v3_debug(v3h, V3_DBG_MEMORY, "initialized speex decoder state"); coder->index = index; coder->format = format; coder->encoder = false; } datalen -= sizeof(uint16_t) * 2; if (datalen < 0) { _v3_debug(v3h, V3_DBG_INFO, "received a malformed speex packet"); ret = V3_MALFORM; break; } data += sizeof(uint16_t) * 2; speex_bits_init(&bits); while (datalen) { framesize = ntohs(*(uint16_t *)data); datalen -= framesize + sizeof(uint16_t); if (!framesize || datalen < 0 || *pcmlen + codec->framesize > maxpcmlen) { _v3_debug(v3h, V3_DBG_INFO, "received a malformed speex packet"); ret = V3_MALFORM; break; } data += sizeof(uint16_t); speex_bits_read_from(&bits, (void *)data, framesize); speex_decode_int(coder->state, &bits, (void *)pcm); speex_bits_reset(&bits); data += framesize; pcm += codec->framesize; *pcmlen += codec->framesize; } speex_bits_destroy(&bits); if (rate) { *rate = codec->rate; } } break; #endif default: (void)rate, (void)maxpcmlen; _v3_debug(v3h, V3_DBG_INFO, "unsupported codec: index: %i | format: %i", index, format); ret = V3_FAILURE; break; } _v3_leave(v3h, __func__); return ret; }
int _v3_audio_encode( v3_handle v3h, /* pcm input */ const uint8_t *pcm, uint32_t pcmlen, /* payload output */ int16_t index, int16_t format, v3_coder *coder, uint8_t *data, uint32_t *datalen, /* optional args */ uint8_t channels) { uint32_t maxdatalen; int ret = V3_OK; _v3_enter(v3h, __func__); if (!pcm || !pcmlen || !coder || !data || !datalen || (datalen && !*datalen)) { _v3_leave(v3h, __func__); return V3_FAILURE; } maxdatalen = *datalen; *datalen = 0; channels = (channels == 2) ? 2 : 1; if (coder->state && (coder->index != index || coder->format != format)) { _v3_coder_destroy(v3h, coder); } switch (index) { #ifdef HAVE_GSM case 0: { const v3_codec *codec = v3_codec_get(index, format); int opt = 1; size_t ctr; _v3_debug(v3h, V3_DBG_INFO, "encoding %u bytes of pcm to gsm @ %u", pcmlen, codec->rate); if (!coder->state) { if (!(coder->state = gsm_create())) { _v3_debug(v3h, V3_DBG_INFO, "failed to create gsm encoder"); ret = V3_FAILURE; break; } gsm_option(coder->state, GSM_OPT_WAV49, &opt); coder->index = index; coder->format = format; coder->encoder = true; } for (ctr = 0; ctr < pcmlen / codec->framesize && *datalen + 65 <= maxdatalen; ++ctr) { gsm_encode(coder->state, (void *)pcm, (void *)data); gsm_encode(coder->state, (void *)pcm+(codec->framesize/2), (void *)data+32); pcm += codec->framesize; data += 65; *datalen += 65; } } break; #endif #ifdef HAVE_OPUS case 1: case 2: { const v3_codec *codec = v3_codec_get(index, format); int tmp; _v3_debug(v3h, V3_DBG_INFO, "encoding %u bytes of pcm to opus @ %u", pcmlen, codec->rate); if (!coder->state || channels != coder->channels) { if (coder->state) { opus_encoder_destroy(coder->state); coder->state = NULL; _v3_debug(v3h, V3_DBG_MEMORY, "released opus state"); } if (!(coder->state = opus_encoder_create(codec->rate, channels, OPUS_APPLICATION_AUDIO, &tmp))) { _v3_debug(v3h, V3_DBG_INFO, "failed to create opus encoder: %s", opus_strerror(tmp)); ret = V3_FAILURE; break; } if ((tmp = opus_encoder_ctl(coder->state, OPUS_SET_COMPLEXITY(10))) != OPUS_OK) { _v3_debug(v3h, V3_DBG_INFO, "opus_encoder_ctl: OPUS_SET_COMPLEXITY: %s", opus_strerror(tmp)); opus_encoder_destroy(coder->state); coder->state = NULL; ret = V3_FAILURE; break; } if ((tmp = opus_encoder_ctl(coder->state, OPUS_SET_VBR(0))) != OPUS_OK) { _v3_debug(v3h, V3_DBG_INFO, "opus_encoder_ctl: OPUS_SET_VBR: %s", opus_strerror(tmp)); opus_encoder_destroy(coder->state); coder->state = NULL; ret = V3_FAILURE; break; } if ((tmp = opus_encoder_ctl(coder->state, OPUS_SET_BITRATE(((index == 1) ? 79 : 43) * 1000))) != OPUS_OK) { _v3_debug(v3h, V3_DBG_INFO, "opus_encoder_ctl: OPUS_SET_BITRATE: %s", opus_strerror(tmp)); opus_encoder_destroy(coder->state); coder->state = NULL; ret = V3_FAILURE; break; } coder->index = index; coder->format = format; coder->channels = channels; coder->encoder = true; } maxdatalen = (maxdatalen <= ((index == 1) ? 198 : 108)) ? maxdatalen : ((index == 1) ? 198 : 108); if ((tmp = opus_encode(coder->state, (void *)pcm, codec->framesize / sizeof(int16_t), (void *)data, maxdatalen)) <= 0) { _v3_debug(v3h, V3_DBG_INFO, "failed to encode opus packet"); } *datalen = tmp; } break; #endif #ifdef HAVE_SPEEX case 3: { static const uint16_t maxspxbuf = 200; const v3_codec *codec = v3_codec_get(index, format); uint16_t framesize; SpeexBits bits; size_t ctr; _v3_debug(v3h, V3_DBG_INFO, "encoding %u bytes of pcm to speex @ %u", pcmlen, codec->rate); if (!coder->state) { switch (codec->rate) { case 8000: coder->state = speex_encoder_init(&speex_nb_mode); break; case 16000: coder->state = speex_encoder_init(&speex_wb_mode); break; case 32000: coder->state = speex_encoder_init(&speex_uwb_mode); break; } if (!coder->state) { _v3_debug(v3h, V3_DBG_INFO, "failed to create speex encoder"); ret = V3_FAILURE; break; } speex_encoder_ctl(coder->state, SPEEX_SET_QUALITY, (void *)&codec->quality); coder->index = index; coder->format = format; coder->encoder = true; } *(uint16_t *)data = htons(pcmlen / codec->framesize); data += sizeof(uint16_t); *datalen += sizeof(uint16_t); *(uint16_t *)data = htons(codec->framesize / sizeof(int16_t)); data += sizeof(uint16_t); *datalen += sizeof(uint16_t); speex_bits_init(&bits); for (ctr = 0; ctr < pcmlen / codec->framesize && *datalen + maxspxbuf <= maxdatalen; ++ctr) { speex_encode_int(coder->state, (void *)pcm, &bits); framesize = speex_bits_write(&bits, (void *)data + sizeof(uint16_t), maxspxbuf); speex_bits_reset(&bits); *(uint16_t *)data = htons(framesize); pcm += codec->framesize; data += sizeof(uint16_t) + framesize; *datalen += sizeof(uint16_t) + framesize; } speex_bits_destroy(&bits); } break; #endif default: (void)maxdatalen; _v3_debug(v3h, V3_DBG_INFO, "unsupported codec: index: %i | format: %i", index, format); ret = V3_FAILURE; break; } _v3_leave(v3h, __func__); return ret; }