/*! \brief encode the temporary buffer and generate a frame */ static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt) { struct ilbc_coder_pvt *tmp = pvt->pvt; int datalen = 0; int samples = 0; /* We can't work on anything less than a frame in size */ if (pvt->samples < ILBC_SAMPLES) return NULL; while (pvt->samples >= ILBC_SAMPLES) { float tmpf[ILBC_SAMPLES]; int i; /* Encode a frame of data */ for (i = 0 ; i < ILBC_SAMPLES ; i++) tmpf[i] = tmp->buf[samples + i]; iLBC_encode( pvt->outbuf.uc + datalen, tmpf, &tmp->enc); datalen += ILBC_FRAME_LEN; samples += ILBC_SAMPLES; pvt->samples -= ILBC_SAMPLES; } /* Move the data at the end of the buffer to the front */ if (pvt->samples) memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); return ast_trans_frameout(pvt, datalen, samples); }
/*! \brief encode and produce a frame */ static struct ast_frame *lintocodec2_frameout(struct ast_trans_pvt *pvt) { struct codec2_translator_pvt *tmp = pvt->pvt; struct ast_frame *result = NULL; struct ast_frame *last = NULL; int samples = 0; /* output samples */ while (pvt->samples >= CODEC2_SAMPLES) { struct ast_frame *current; /* Encode a frame of data */ codec2_encode(tmp->state, pvt->outbuf.uc, tmp->buf + samples); samples += CODEC2_SAMPLES; pvt->samples -= CODEC2_SAMPLES; current = ast_trans_frameout(pvt, CODEC2_FRAME_LEN, CODEC2_SAMPLES); if (!current) { continue; } else if (last) { AST_LIST_NEXT(last, frame_list) = current; } else { result = current; } last = current; } /* Move the data at the end of the buffer to the front */ if (samples) { memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); } return result; }
/*! \brief encode and produce a frame */ static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt) { struct gsm_translator_pvt *tmp = pvt->pvt; int datalen = 0; int samples = 0; /* We can't work on anything less than a frame in size */ if (pvt->samples < GSM_SAMPLES) return NULL; while (pvt->samples >= GSM_SAMPLES) { /* Encode a frame of data */ gsm_encode(tmp->gsm, tmp->buf, (gsm_byte *)pvt->outbuf + datalen); datalen += GSM_FRAME_LEN; samples += GSM_SAMPLES; pvt->samples -= GSM_SAMPLES; /* Move the data at the end of the buffer to the front */ if (pvt->samples) memmove(tmp->buf, tmp->buf + GSM_SAMPLES, pvt->samples * 2); } return ast_trans_frameout(pvt, datalen, samples); }
static struct ast_frame *lintoopus_frameout(struct ast_trans_pvt *pvt) { struct opus_coder_pvt *opvt = pvt->pvt; int datalen = 0; /* output bytes */ int samples = 0; /* output samples */ /* We can't work on anything less than a frame in size */ if (pvt->samples < opvt->framesize) { return NULL; } /* Encode 160 samples (or more if it's not narrowband) */ ast_debug(3, "[Encoder #%d (%d)] %d samples, %d bytes\n", opvt->id, opvt->sampling_rate, opvt->framesize, opvt->framesize * 2); if ((datalen = opus_encode(opvt->opus, opvt->buf, opvt->framesize, pvt->outbuf.uc, BUFFER_SAMPLES)) < 0) { ast_log(LOG_ERROR, "Error encoding the Opus frame: %s\n", opus_strerror(datalen)); return NULL; } samples += opvt->framesize; pvt->samples -= opvt->framesize; /* Move the data at the end of the buffer to the front */ if (pvt->samples) { memmove(opvt->buf, opvt->buf + samples, pvt->samples * 2); } ast_debug(3, "[Encoder #%d (%d)] >> Got %d samples, %d bytes\n", opvt->id, opvt->sampling_rate, opvt->multiplier * samples, datalen); return ast_trans_frameout(pvt, datalen, opvt->multiplier * samples); }
/*! \brief convert work buffer and produce output frame */ static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt) { struct speex_coder_pvt *tmp = pvt->pvt; int is_speech=1; int datalen = 0; /* output bytes */ int samples = 0; /* output samples */ /* We can't work on anything less than a frame in size */ if (pvt->samples < tmp->framesize) return NULL; speex_bits_reset(&tmp->bits); while (pvt->samples >= tmp->framesize) { #ifdef _SPEEX_TYPES_H /* Preprocess audio */ if (preproc) is_speech = speex_preprocess(tmp->pp, tmp->buf + samples, NULL); /* Encode a frame of data */ if (is_speech) { /* If DTX enabled speex_encode returns 0 during silence */ is_speech = speex_encode_int(tmp->speex, tmp->buf + samples, &tmp->bits) || !dtx; } else { /* 5 zeros interpreted by Speex as silence (submode 0) */ speex_bits_pack(&tmp->bits, 0, 5); } #else { float fbuf[1024]; int x; /* Convert to floating point */ for (x = 0; x < tmp->framesize; x++) fbuf[x] = tmp->buf[samples + x]; /* Encode a frame of data */ is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx; } #endif samples += tmp->framesize; pvt->samples -= tmp->framesize; } /* Move the data at the end of the buffer to the front */ if (pvt->samples) memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); /* Use AST_FRAME_CNG to signify the start of any silence period */ if (is_speech) { tmp->silent_state = 0; } else { if (tmp->silent_state) { return NULL; } else { tmp->silent_state = 1; speex_bits_reset(&tmp->bits); memset(&pvt->f, 0, sizeof(pvt->f)); pvt->f.frametype = AST_FRAME_CNG; pvt->f.samples = samples; /* XXX what now ? format etc... */ } } /* Terminate bit stream */ speex_bits_pack(&tmp->bits, 15, 5); datalen = speex_bits_write(&tmp->bits, pvt->outbuf.c, pvt->t->buf_size); return ast_trans_frameout(pvt, datalen, samples); }
/*! \brief convert work buffer and produce output frame */ static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt) { struct speex_coder_pvt *tmp = pvt->pvt; int is_speech=1; int datalen = 0; /* output bytes */ int samples = 0; /* output samples */ /* We can't work on anything less than a frame in size */ if (pvt->samples < tmp->framesize) return NULL; speex_bits_reset(&tmp->bits); while (pvt->samples >= tmp->framesize) { #ifdef _SPEEX_TYPES_H /* Preprocess audio */ if (preproc) is_speech = speex_preprocess(tmp->pp, tmp->buf + samples, NULL); /* Encode a frame of data */ if (is_speech) { /* If DTX enabled speex_encode returns 0 during silence */ is_speech = speex_encode_int(tmp->speex, tmp->buf + samples, &tmp->bits) || !dtx; } else { /* 5 zeros interpreted by Speex as silence (submode 0) */ speex_bits_pack(&tmp->bits, 0, 5); } #else { float fbuf[1024]; int x; /* Convert to floating point */ for (x = 0; x < tmp->framesize; x++) fbuf[x] = tmp->buf[samples + x]; /* Encode a frame of data */ is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx; } #endif samples += tmp->framesize; pvt->samples -= tmp->framesize; } /* Move the data at the end of the buffer to the front */ if (pvt->samples) memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); /* Use AST_FRAME_CNG to signify the start of any silence period */ if (is_speech) { tmp->silent_state = 0; } else { if (tmp->silent_state) { return NULL; } else { struct ast_frame frm = { .frametype = AST_FRAME_CNG, .src = pvt->t->name, }; /* * XXX I don't think the AST_FRAME_CNG code has ever * really worked for speex. There doesn't seem to be * any consumers of the frame type. Everyone that * references the type seems to pass the frame on. */ tmp->silent_state = 1; /* XXX what now ? format etc... */ return ast_frisolate(&frm); } } /* Terminate bit stream */ speex_bits_pack(&tmp->bits, 15, 5); datalen = speex_bits_write(&tmp->bits, pvt->outbuf.c, pvt->t->buf_size); return ast_trans_frameout(pvt, datalen, samples); } static void speextolin_destroy(struct ast_trans_pvt *arg) { struct speex_coder_pvt *pvt = arg->pvt; speex_decoder_destroy(pvt->speex); speex_bits_destroy(&pvt->bits); } static void lintospeex_destroy(struct ast_trans_pvt *arg) { struct speex_coder_pvt *pvt = arg->pvt; #ifdef _SPEEX_TYPES_H if (preproc) speex_preprocess_state_destroy(pvt->pp); #endif speex_encoder_destroy(pvt->speex); speex_bits_destroy(&pvt->bits); } static struct ast_translator speextolin = { .name = "speextolin", .src_codec = { .name = "speex", .type = AST_MEDIA_TYPE_AUDIO, .sample_rate = 8000, }, .dst_codec = { .name = "slin", .type = AST_MEDIA_TYPE_AUDIO, .sample_rate = 8000, }, .format = "slin",