Пример #1
0
static switch_status_t switch_amrwb_encode(switch_codec_t *codec,
										   switch_codec_t *other_codec,
										   void *decoded_data,
										   uint32_t decoded_data_len,
										   uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate,
										   unsigned int *flag)
{
#ifdef AMRWB_PASSTHROUGH
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This codec is only usable in passthrough mode!\n");
	return SWITCH_STATUS_FALSE;
#else
	struct amrwb_context *context = codec->private_info;

	if (!context) {
		return SWITCH_STATUS_FALSE;
	}

	*encoded_data_len = E_IF_encode(context->encoder_state, context->enc_mode, (int16_t *) decoded_data, (switch_byte_t *) encoded_data, 0);

	return SWITCH_STATUS_SUCCESS;
#endif
}
Пример #2
0
/*
 * Encode frame.
 */
static pj_status_t amr_codec_encode( pjmedia_codec *codec, 
				     const struct pjmedia_frame *input,
				     unsigned output_buf_len, 
				     struct pjmedia_frame *output)
{
    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
    unsigned char *bitstream;
    pj_int16_t *speech;
    unsigned nsamples, samples_per_frame;
    enum {MAX_FRAMES_PER_PACKET = 16};
    pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
    pj_uint8_t *p;
    unsigned i, out_size = 0, nframes = 0;
    pj_size_t payload_len;
    unsigned dtx_cnt, sid_cnt;
    pj_status_t status;

    pj_assert(amr_data != NULL);
    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);

    nsamples = input->size >> 1;
    samples_per_frame = amr_data->clock_rate * FRAME_LENGTH_MS / 1000;
    PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0, 
		     PJMEDIA_CODEC_EPCMFRMINLEN);

    nframes = nsamples / samples_per_frame;
    PJ_ASSERT_RETURN(nframes <= MAX_FRAMES_PER_PACKET, 
		     PJMEDIA_CODEC_EFRMTOOSHORT);

    /* Encode the frames */
    speech = (pj_int16_t*)input->buf;
    bitstream = (unsigned char*)output->buf;
    while (nsamples >= samples_per_frame) {
	int size;
        if (amr_data->enc_setting.amr_nb) {
#ifdef USE_AMRNB
            size = Encoder_Interface_Encode (amr_data->encoder,
                                             amr_data->enc_mode,
                                             speech, bitstream, 0);
#else
            size = 0;
#endif
        } else {
#ifdef USE_AMRWB
            size = E_IF_encode (amr_data->encoder, amr_data->enc_mode,
                                speech, bitstream, 0);
#else
            size = 0;
#endif
        }
	if (size == 0) {
	    output->size = 0;
	    output->buf = NULL;
	    output->type = PJMEDIA_FRAME_TYPE_NONE;
	    TRACE_((THIS_FILE, "AMR encode() failed"));
	    return PJMEDIA_CODEC_EFAILED;
	}
	nsamples -= samples_per_frame;
	speech += samples_per_frame;
	bitstream += size;
	out_size += size;
	TRACE_((THIS_FILE, "AMR encode(): mode=%d, size=%d",
		amr_data->enc_mode, out_size));
    }

    /* Pack payload */
    p = (pj_uint8_t*)output->buf + output_buf_len - out_size;
    pj_memmove(p, output->buf, out_size);
    dtx_cnt = sid_cnt = 0;
    for (i = 0; i < nframes; ++i) {
	pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*)
					   &frames[i].bit_info;
	info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F);
	info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01);
	info->mode = (pj_int8_t)amr_data->enc_mode;
	info->start_bit = 0;
	frames[i].buf = p + 1;
        if (amr_data->enc_setting.amr_nb) {
            frames[i].size = (info->frame_type <= 8)?
                             pjmedia_codec_amrnb_framelen[info->frame_type] : 0;
        } else {
            frames[i].size = (info->frame_type <= 9)?
                             pjmedia_codec_amrwb_framelen[info->frame_type] : 0;
        }
	p += frames[i].size + 1;

	/* Count the number of SID and DTX frames */
	if (info->frame_type == 15) /* DTX*/
	    ++dtx_cnt;
	else if (info->frame_type == 8) /* SID */
	    ++sid_cnt;
    }

    /* VA generates DTX frames as DTX+SID frames switching quickly and it
     * seems that the SID frames occur too often (assuming the purpose is 
     * only for keeping NAT alive?). So let's modify the behavior a bit.
     * Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD
     * milliseconds.
     */
    if (sid_cnt + dtx_cnt == nframes) {
	pj_int32_t dtx_duration;

	dtx_duration = pj_timestamp_diff32(&amr_data->last_tx, 
					   &input->timestamp);
	if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
	    dtx_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*
                           amr_data->clock_rate/1000)
	{
	    output->size = 0;
	    output->type = PJMEDIA_FRAME_TYPE_NONE;
	    output->timestamp = input->timestamp;
	    return PJ_SUCCESS;
	}
    }

    payload_len = output_buf_len;

    status = pjmedia_codec_amr_pack(frames, nframes, &amr_data->enc_setting,
				    output->buf, &payload_len);
    if (status != PJ_SUCCESS) {
	output->size = 0;
	output->buf = NULL;
	output->type = PJMEDIA_FRAME_TYPE_NONE;
	TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status));
	return status;
    }

    output->size = payload_len;
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
    output->timestamp = input->timestamp;

    amr_data->last_tx = input->timestamp;

    return PJ_SUCCESS;
}
Пример #3
0
int main(int argc, char *argv[])
{
   FILE *f_speech = NULL;                 /* File of speech data                   */
   FILE *f_serial = NULL;                 /* File of serial bits for transmission  */
   FILE *f_mode = NULL;                   /* File of modes for each frame          */

   Word32 serial_size, frame;
   Word16 signal[L_FRAME16k];             /* Buffer for speech @ 16kHz             */
   Word16 coding_mode = 0, allow_dtx, mode_file, mode = 0;
   UWord8 serial[NB_SERIAL_MAX];
   void *st;

   fprintf(stderr, "\n");
   fprintf(stderr, "===================================================================\n");
   fprintf(stderr, " 3GPP AMR-WB Floating-point Speech Coder, v6.0.0, Dec 14, 2004\n");
   fprintf(stderr, "===================================================================\n");
   fprintf(stderr, "\n");

   /*
    * Open speech file and result file (output serial bit stream)
    */

   if ((argc < 4) || (argc > 6))
   {
      fprintf(stderr, "Usage : encoder  (-dtx) mode speech_file  bitstream_file\n");
      fprintf(stderr, "\n");
      fprintf(stderr, "Format for speech_file:\n");
      fprintf(stderr, "  Speech is read form a binary file of 16 bits data.\n");
      fprintf(stderr, "\n");
      fprintf(stderr, "Format for bitstream_file:\n");
#ifdef IF2
      fprintf(stderr, "  Described in TS26.201.\n");
#else
      fprintf(stderr, "  Described in RFC 3267 (Sections 5.1 and 5.3).\n");
#endif
      fprintf(stderr, "\n");
      fprintf(stderr, "mode: 0 to 8 (9 bits rates) or\n");
      fprintf(stderr, "      -modefile filename\n");
      fprintf(stderr, " ===================================================================\n");
      fprintf(stderr, " mode   :  (0)  (1)   (2)   (3)   (4)   (5)   (6)   (7)   (8)     \n");
      fprintf(stderr, " bitrate: 6.60 8.85 12.65 14.25 15.85 18.25 19.85 23.05 23.85 kbit/s\n");
      fprintf(stderr, " ===================================================================\n");
      fprintf(stderr, "\n");
      fprintf(stderr, "-dtx if DTX is ON, default is OFF\n");
      fprintf(stderr, "\n");
      exit(0);
   }
   allow_dtx = 0;
   if (strcmp(argv[1], "-dtx") == 0)
   {
      allow_dtx = 1;
      argv++;
   }
   mode_file = 0;
   if (strcmp(argv[1], "-modefile") == 0)
   {
      mode_file = 1;
      argv++;
      if ((f_mode = fopen(argv[1], "r")) == NULL)
      {
         fprintf(stderr, "Error opening input file  %s !!\n", argv[1]);
         exit(0);
      }
      fprintf(stderr, "Mode file:  %s\n", argv[1]);
   }
   else
   {
      mode = (Word16) atoi(argv[1]);
      if ((mode < 0) || (mode > 8))
      {
         fprintf(stderr, " error in bit rate mode %d: use 0 to 8\n", mode);
         exit(0);
      }
   }

   if ((f_speech = fopen(argv[2], "rb")) == NULL)
   {
      fprintf(stderr, "Error opening input file  %s !!\n", argv[2]);
      exit(0);
   }
   fprintf(stderr, "Input speech file:  %s\n", argv[2]);

   if ((f_serial = fopen(argv[3], "wb")) == NULL)
   {
      fprintf(stderr, "Error opening output bitstream file %s !!\n", argv[3]);
      exit(0);
   }
   fprintf(stderr, "Output bitstream file:  %s\n", argv[3]);

   /*
    * Initialisation
    */

   st = E_IF_init();

#ifndef IF2

   /* If MMS output is selected, write the magic number at the beginning of the
    * bitstream file
	*/

	fwrite(AMRWB_MAGIC_NUMBER, sizeof(char), strlen(AMRWB_MAGIC_NUMBER), f_serial);

#endif

   /*
    * Loop for every analysis/transmission frame.
    *   -New L_FRAME data are read. (L_FRAME = number of speech data per frame)
    *   -Conversion of the speech data from 16 bit integer to real
    *   -Call coder to encode the speech.
    *   -The compressed serial output stream is written to a file.
    */

   fprintf(stderr, "\n --- Running ---\n");

   frame = 0;

   while (fread(signal, sizeof(Word16), L_FRAME16k, f_speech) == L_FRAME16k)
   {
      if (mode_file)
      {
         if (fscanf(f_mode, "%hd", &mode) == EOF)
         {
            mode = coding_mode;
            fprintf(stderr, "\n end of mode control file reached\n");
            fprintf(stderr, " From now on using mode: %hd.\n", mode);
            mode_file = 0;
         }

         if ((mode < 0) || (mode > 8))
         {
            fprintf(stderr, " error in bit rate mode %hd: use 0 to 8\n", mode);
            E_IF_exit(st);
            fclose(f_speech);
            fclose(f_serial);
            fclose(f_mode);
            exit(0);
         }
      }

      coding_mode = mode;

      frame++;
      fprintf(stderr, " Frames processed: %ld\r", frame);

      serial_size = E_IF_encode(st, coding_mode, signal, serial, allow_dtx);

      fwrite(serial, 1, serial_size, f_serial);

   }

   E_IF_exit(st);

   fclose(f_speech);
   fclose(f_serial);

   if (f_mode != NULL)
   {
      fclose(f_mode);
   }

   return 0;
}
Пример #4
0
static GstFlowReturn
gst_voamrwbenc_chain (GstPad * pad, GstBuffer * buffer)
{
  GstVoAmrWbEnc *amrwbenc;
  GstFlowReturn ret = GST_FLOW_OK;
  const int buffer_size = sizeof (short) * L_FRAME16k;

  amrwbenc = GST_VOAMRWBENC (gst_pad_get_parent (pad));

  g_return_val_if_fail (amrwbenc->handle, GST_FLOW_WRONG_STATE);

  if (amrwbenc->rate == 0 || amrwbenc->channels == 0) {
    ret = GST_FLOW_NOT_NEGOTIATED;
    goto done;
  }

  /* discontinuity clears adapter, FIXME, maybe we can set some
   * encoder flag to mask the discont. */
  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
    gst_adapter_clear (amrwbenc->adapter);
    amrwbenc->ts = 0;
    amrwbenc->discont = TRUE;
  }

  if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
    amrwbenc->ts = GST_BUFFER_TIMESTAMP (buffer);

  ret = GST_FLOW_OK;
  gst_adapter_push (amrwbenc->adapter, buffer);

  /* Collect samples until we have enough for an output frame */
  while (gst_adapter_available (amrwbenc->adapter) >= buffer_size) {
    GstBuffer *out;
    guint8 *data;
    gint outsize;

    out = gst_buffer_new_and_alloc (buffer_size);
    GST_BUFFER_DURATION (out) = GST_SECOND * L_FRAME16k /
        (amrwbenc->rate * amrwbenc->channels);
    GST_BUFFER_TIMESTAMP (out) = amrwbenc->ts;
    if (amrwbenc->ts != -1) {
      amrwbenc->ts += GST_BUFFER_DURATION (out);
    }
    if (amrwbenc->discont) {
      GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DISCONT);
      amrwbenc->discont = FALSE;
    }
    gst_buffer_set_caps (out, gst_pad_get_caps (amrwbenc->srcpad));

    data = (guint8 *) gst_adapter_peek (amrwbenc->adapter, buffer_size);

    /* encode */
    outsize =
        E_IF_encode (amrwbenc->handle, amrwbenc->bandmode, (const short *) data,
        (unsigned char *) GST_BUFFER_DATA (out), 0);

    gst_adapter_flush (amrwbenc->adapter, buffer_size);
    GST_BUFFER_SIZE (out) = outsize;

    /* play */
    if ((ret = gst_pad_push (amrwbenc->srcpad, out)) != GST_FLOW_OK)
      break;
  }

done:

  gst_object_unref (amrwbenc);
  return ret;

}