Exemplo n.º 1
0
void AmJbPlayout::prepare_buffer(unsigned int audio_buffer_ts, unsigned int ms)
{
  ShortSample buf[AUDIO_BUFFER_SIZE];
  unsigned int ts;
  unsigned int nb_samples;
  /**
   * Get all RTP packets that correspond to the required interval,
   * decode them and put into playout buffer.
   */
  while (m_jb.get(audio_buffer_ts, ms, buf, &nb_samples, &ts))
    {
      direct_write_buffer(ts, buf, nb_samples);
      m_plcbuffer->add_to_history(buf, PCM16_S2B(nb_samples));
      /* Conceal the gap between previous and current RTP packets */
      if (last_ts_i && ts_less()(m_last_rtp_endts, ts))
       	{
	  int concealed_size = m_plcbuffer->conceal_loss(ts - m_last_rtp_endts, (unsigned char *)buf);
	  if (concealed_size > 0)
	    direct_write_buffer(m_last_rtp_endts, buf, PCM16_B2S(concealed_size));
	}
      m_last_rtp_endts = ts + nb_samples;
      last_ts_i = true;
    }
  if (!last_ts_i) {
    return;
  }
  if (ts_less()(m_last_rtp_endts, audio_buffer_ts + ms))
    {
      /* Last packets have been lost. Conceal them */
      int concealed_size = m_plcbuffer->conceal_loss(audio_buffer_ts + ms - m_last_rtp_endts, (unsigned char *)buf);
      if (concealed_size > 0)
	direct_write_buffer(m_last_rtp_endts, buf, PCM16_B2S(concealed_size));
      m_last_rtp_endts = audio_buffer_ts + ms;
    }
}
Exemplo n.º 2
0
unsigned int AmInternalResamplerState::resample(unsigned char *samples, unsigned int s, double ratio)
{
  if (rstate == NULL) {
    ERROR("Uninitialized resampling state");
    return s;
  }

  //DBG("Resampling with ration %f", ratio);
  //DBG("Putting %d samples in the buffer", PCM16_B2S(s));
  rstate->put_samples((signed short *)samples, PCM16_B2S(s));
  s = rstate->resample((signed short *)samples, ratio, PCM16_B2S(s) * ratio);
  //DBG("Returning %d samples", s);
  return PCM16_S2B(s);
}
Exemplo n.º 3
0
u_int32_t AmPlayoutBuffer::read(u_int32_t ts, int16_t* buf, u_int32_t len)
{
    if(ts_less()(r_ts,w_ts)){

	u_int32_t rlen=0;
	if(ts_less()(r_ts+PCM16_B2S(AUDIO_BUFFER_SIZE),w_ts))
	    rlen = PCM16_B2S(AUDIO_BUFFER_SIZE);
	else
	    rlen = w_ts - r_ts;

	buffer_get(r_ts,buf,rlen);
	return rlen;
    }

    return 0;
}
Exemplo n.º 4
0
void AmMultiPartyMixer::PutChannelPacket(unsigned int   channel_id,
					 unsigned long long system_ts, 
					 unsigned char* buffer, 
					 unsigned int   size)
{
  if(!size)
    return;
  assert(size <= AUDIO_BUFFER_SIZE);

  std::deque<MixerBufferState>::iterator bstate = findOrCreateBufferState(GetCurrentSampleRate());

  SampleArrayShort* channel = 0;
  if((channel = bstate->get_channel(channel_id)) != 0) {

    unsigned samples = PCM16_B2S(size);
    unsigned long long put_ts = system_ts + (MIXER_DELAY_MS * WALLCLOCK_RATE / 1000);
    unsigned long long user_put_ts = put_ts * (GetCurrentSampleRate()/100) / (WALLCLOCK_RATE/100);

    channel->put(user_put_ts,(short*)buffer,samples);
    bstate->mixed_channel->get(user_put_ts,tmp_buffer,samples);

    mix_add(tmp_buffer,tmp_buffer,(short*)buffer,samples);
    bstate->mixed_channel->put(user_put_ts,tmp_buffer,samples);
    bstate->last_ts = put_ts + (samples * (WALLCLOCK_RATE/100) / (GetCurrentSampleRate()/100));
  } else {
    /*
    ERROR("XXDebugMixerXX: MultiPartyMixer::PutChannelPacket: "
	  "channel #%i doesn't exist\n",channel_id);
    DBG("XXDebugMixer:: PutChannelPacket failed ts=%u", ts);
    for (std::deque<MixerBufferState>::iterator it = buffer_state.begin(); it != buffer_state.end(); it++) {
      DEBUG_MIXER_BUFFER_STATE(*it, "on PutChannelPacket failure");
      }*/
  }
}
Exemplo n.º 5
0
void Packet::init(const ShortSample *data, unsigned int size, unsigned int ts)
{
  size = PCM16_S2B(size);
  if (size > sizeof(m_data))
    size = sizeof(m_data);
  m_size = PCM16_B2S(size);
  memcpy(m_data, data, size);
  m_ts = ts;
}
Exemplo n.º 6
0
void AmRtpAudio::add_to_history(int16_t *buffer, unsigned int size)
{
  if (!use_default_plc)
    return;

#ifdef USE_SPANDSP_PLC
  plc_rx(plc_state, buffer, PCM16_B2S(size));
#else // USE_SPANDSP_PLC
  int16_t* buf_offset = buffer;

  unsigned int sample_rate = getSampleRate();

  for(unsigned int i=0; i<(PCM16_B2S(size)/FRAMESZ); i++){
    fec->addtohistory(buf_offset);
    buf_offset += FRAMESZ;
  }
#endif // USE_SPANDSP_PLC
}
Exemplo n.º 7
0
void AmMultiPartyMixer::GetChannelPacket(unsigned int   channel_id,
					 unsigned long long system_ts, 
					 unsigned char* buffer, 
					 unsigned int&  size,
					 unsigned int&  output_sample_rate)
{
  if (!size)
    return;
  assert(size <= AUDIO_BUFFER_SIZE);

  unsigned int last_ts = system_ts + (PCM16_B2S(size) * (WALLCLOCK_RATE/100) / (GetCurrentSampleRate()/100));
  std::deque<MixerBufferState>::iterator bstate = findBufferStateForReading(GetCurrentSampleRate(), last_ts);

  SampleArrayShort* channel = 0;
  if(bstate != buffer_state.end() && (channel = bstate->get_channel(channel_id)) != 0) {

    unsigned int samples = PCM16_B2S(size) * (bstate->sample_rate/100) / (GetCurrentSampleRate()/100);
    assert(samples <= PCM16_B2S(AUDIO_BUFFER_SIZE));

    unsigned long long cur_ts = system_ts * (bstate->sample_rate/100) / (WALLCLOCK_RATE/100);
    bstate->mixed_channel->get(cur_ts,tmp_buffer,samples);
    channel->get(cur_ts,(short*)buffer,samples);

    mix_sub(tmp_buffer,tmp_buffer,(short*)buffer,samples);
    scale((short*)buffer,tmp_buffer,samples);
    size = PCM16_S2B(samples);
    output_sample_rate = bstate->sample_rate;
  } else if (bstate != buffer_state.end()) {
    memset(buffer,0,size);
    output_sample_rate = GetCurrentSampleRate();
    //DBG("XXDebugMixerXX: GetChannelPacket returned zeroes, ts=%u, last_ts=%u, output_sample_rate=%u", ts, last_ts, output_sample_rate);
  } else {
    /*
    ERROR("XXDebugMixerXX: MultiPartyMixer::GetChannelPacket: "
	  "channel #%i doesn't exist\n",channel_id);
    DBG("XXDebugMixerXX: GetChannelPacket failed, ts=%u", ts);
    for (std::deque<MixerBufferState>::iterator it = buffer_state.begin(); it != buffer_state.end(); it++) {
      DEBUG_MIXER_BUFFER_STATE(*it, "on GetChannelPacket failure");
      }*/
  }

  cleanupBufferStates(last_ts);
}
Exemplo n.º 8
0
unsigned int AmRtpAudio::default_plc(unsigned char* out_buf,
				     unsigned int   size,
				     unsigned int   channels,
				     unsigned int   sample_rate)
{
  short* buf_offset = (short*)out_buf;

#ifdef USE_SPANDSP_PLC
  plc_fillin(plc_state, buf_offset, PCM16_B2S(size));
#else
  for(unsigned int i=0; i<(PCM16_B2S(size)/FRAMESZ); i++){

    fec->dofe(buf_offset);
    buf_offset += FRAMESZ;
  }
#endif // USE_SPANDSP_PLC

  return PCM16_S2B(buf_offset - (short*)out_buf);
}
Exemplo n.º 9
0
void AmBufferedAudio::input_get_audio(unsigned int user_ts) {
  if (r && (r != w)) {
    // move contents to beginning of buffer
    memmove(output_buffer, &output_buffer[r], w-r);
    w -= r; 
    r = 0;
  }
  while (w < full_buffer_thresh) {
    int size = calcBytesToRead(PCM16_B2S(output_buffer_size - w));

//     DBG("calc %d bytes to read\n", size);
    
    // resync might be delayed until buffer empty     // (but output resync never happens)
    size = read(user_ts + PCM16_B2S(w-r),size);
//     DBG("read returned size = %d\n",size);
    if(size <= 0){
      err_code = size;
      eof = true;
      return;
    }
    
    size = decode(size);
    if(size < 0) {
//       DBG("decode returned %i\n",size);
      err_code = size;
      eof = true;
      return; 
    }

//     DBG("decode returned %i\n",size);
    size = downMixChannels(size);
    
    size = downMixRate(size);

    
    if(size>0) {
      memcpy(&output_buffer[w],(unsigned char*)samples,size);
      w+=size;
    }
  }
}
Exemplo n.º 10
0
void RtmpAudio::process_recv_queue(unsigned int ref_ts)
{
  int size;

  // flush the recv queue into the playout buffer
  m_q_recv.lock();
  while(!q_recv.empty()){

    RTMPPacket p = q_recv.front();
    q_recv.pop();
    m_q_recv.unlock();

    //TODO:
    // - copy RTMP payload into this->samples
    // - decode
    // - put packet in playout buffer

    if(p.m_nBodySize <= (unsigned int)AUDIO_BUFFER_SIZE){
      

      size = p.m_nBodySize-1;
      memcpy((unsigned char*)samples, p.m_body+1, size);

      size = decode(size);
      if(size <= 0){
	ERROR("decode() returned %i\n",size);
	return;
      }
      
      // TODO: generate some reasonable RTP timestamp
      //
      bool begin_talk = false;
      if(!recv_offset_i){
	recv_rtp_offset  = ref_ts;
	recv_rtmp_offset = p.m_nTimeStamp;
	recv_offset_i = true;
	begin_talk = true;
      }

      unsigned int rtp_ts = (p.m_nTimeStamp - recv_rtmp_offset) * (SPEEX_WB_SAMPLE_RATE/1000);

      playout_buffer.write(ref_ts, rtp_ts, (ShortSample*)((unsigned char *)samples),
			   PCM16_B2S(size), begin_talk);
      
      RTMPPacket_Free(&p);    
    }

    m_q_recv.lock();
  }
  m_q_recv.unlock();
}
Exemplo n.º 11
0
void AmPlayoutBuffer::write(u_int32_t ref_ts, u_int32_t rtp_ts, 
			    int16_t* buf, u_int32_t len, bool begin_talk)
{  
  unsigned int mapped_ts;
  if(!recv_offset_i)
    {
      recv_offset = rtp_ts - ref_ts;
      recv_offset_i = true;
      DBG("initialized recv_offset with %u (%u - %u)\n",
	  recv_offset, ref_ts, rtp_ts);
      mapped_ts = r_ts = w_ts = ref_ts;
    }
  else {
    mapped_ts = rtp_ts - recv_offset;

    // resync
    if( ts_less()(mapped_ts, ref_ts - MAX_DELAY/2) || 
	!ts_less()(mapped_ts, ref_ts + MAX_DELAY) ){

      DBG("resync needed: reference ts = %u; write ts = %u\n",
	  ref_ts, mapped_ts);
      recv_offset = rtp_ts - ref_ts;
      mapped_ts = r_ts = w_ts = ref_ts;
    }
  }

  if(!last_ts_i)
    {
      last_ts = mapped_ts;
      last_ts_i = true;
    }

  if(ts_less()(last_ts, mapped_ts) && !begin_talk
     && (mapped_ts - last_ts <= PLC_MAX_SAMPLES))
    {
      unsigned char tmp[AUDIO_BUFFER_SIZE * 2];
      int l_size = m_plcbuffer->conceal_loss(mapped_ts - last_ts, tmp);
      if (l_size>0)
        {
	  direct_write_buffer(last_ts, (ShortSample*)tmp, PCM16_B2S(l_size));
        }
    }
  write_buffer(ref_ts, mapped_ts, buf, len);

  m_plcbuffer->add_to_history(buf, PCM16_S2B(len));

  // update last_ts to end of received packet 
  // if not out-of-sequence
  if (ts_less()(last_ts, mapped_ts) || last_ts == mapped_ts)
    last_ts = mapped_ts + len;
}
Exemplo n.º 12
0
unsigned int AmAudio::downMix(unsigned int size)
{
  unsigned int s = size;
  if(fmt->channels == 2){
    stereo2mono(samples.back_buffer(),(unsigned char*)samples,s);
    samples.swap();
  }

#ifdef USE_LIBSAMPLERATE 
  if (fmt->rate != SYSTEM_SAMPLERATE) {
    if (!resample_state) {
      int src_error;
      // for better quality but more CPU usage, use SRC_SINC_ converters
      resample_state = src_new(SRC_LINEAR, 1, &src_error);
      if (!resample_state) {
	ERROR("samplerate initialization error: ");
      }
    }

    if (resample_state) {
      if (resample_buf_samples + PCM16_B2S(s) > PCM16_B2S(AUDIO_BUFFER_SIZE) * 2) {
	WARN("resample input buffer overflow! (%d)\n",
	     resample_buf_samples + PCM16_B2S(s));
      } else {
	signed short* samples_s = (signed short*)(unsigned char*)samples;
	src_short_to_float_array(samples_s, &resample_in[resample_buf_samples], PCM16_B2S(s));
	resample_buf_samples += PCM16_B2S(s);
      }
      
      SRC_DATA src_data;
      src_data.data_in = resample_in;
      src_data.input_frames = resample_buf_samples;
      src_data.data_out = resample_out;
      src_data.output_frames = PCM16_B2S(AUDIO_BUFFER_SIZE);
      src_data.src_ratio = (double)SYSTEM_SAMPLERATE / (double)fmt->rate;
      src_data.end_of_input = 0;

      int src_err = src_process(resample_state, &src_data);
      if (src_err) {
	DBG("resample error: '%s'\n", src_strerror(src_err));
      }else {
	signed short* samples_s = (signed short*)(unsigned char*)samples;
	src_float_to_short_array(resample_out, samples_s, src_data.output_frames_gen);
	s = PCM16_S2B(src_data.output_frames_gen);

	if (resample_buf_samples !=  (unsigned int)src_data.input_frames_used) {
	  memmove(resample_in, &resample_in[src_data.input_frames_used], 
		  (resample_buf_samples - src_data.input_frames_used) * sizeof(float));
	}
	resample_buf_samples = resample_buf_samples - src_data.input_frames_used;
      }
    }
  }
#endif
 

  return s;
}
Exemplo n.º 13
0
int AmRingTone::read(unsigned int user_ts, unsigned int size)
{
  int ts_on = on_period*(SYSTEM_SAMPLECLOCK_RATE/1000);
  int ts_off = off_period*(SYSTEM_SAMPLECLOCK_RATE/1000);
  int t = user_ts % (ts_on + ts_off);

  if(length < 0)
    return -1;

  if(t >= ts_on){

    memset((unsigned char*)samples,0,size);

    return size;
  }

  short* s = (short*)((unsigned char*)samples);
  for(unsigned int i=0; i<PCM16_B2S(size); i++, s++, t++){

    if(t < ts_on){
      float fs = sin((float(t*freq)/(float)SYSTEM_SAMPLECLOCK_RATE)*2.0*PI)*15000.0;
      if(freq2 != 0)
	fs += sin((float(t*freq2)/(float)SYSTEM_SAMPLECLOCK_RATE)*2.0*PI)*15000.0;
      *s = (short)(fs);
    }
    else
      *s = 0;

  }

  if(length != 0){
    length -= PCM16_B2S(size) / (SYSTEM_SAMPLECLOCK_RATE/1000);
    if(!length)
      length--;
  }

  return size;
}
Exemplo n.º 14
0
unsigned int AmLibSamplerateResamplingState::resample(unsigned char* samples, unsigned int s, double ratio)
{
  DBG("resampling packet of size %d with ratio %f", s, ratio);
  if (!resample_state) {
    int src_error;
    // for better quality but more CPU usage, use SRC_SINC_ converters
    resample_state = src_new(SRC_LINEAR, 1, &src_error);
    if (!resample_state) {
      ERROR("samplerate initialization error: ");
    }
  }

  if (resample_state) {
    if (resample_buf_samples + PCM16_B2S(s) > PCM16_B2S(AUDIO_BUFFER_SIZE) * 2) {
      WARN("resample input buffer overflow! (%lu)\n", resample_buf_samples + PCM16_B2S(s));
    } else if (resample_out_buf_samples + (PCM16_B2S(s) * ratio) + 20 > PCM16_B2S(AUDIO_BUFFER_SIZE)) {
      WARN("resample: possible output buffer overflow! (%lu)\n", (resample_out_buf_samples + (size_t) ((PCM16_B2S(s) * ratio)) + 20));
    } else {
      signed short* samples_s = (signed short*)samples;
      src_short_to_float_array(samples_s, &resample_in[resample_buf_samples], PCM16_B2S(s));
      resample_buf_samples += PCM16_B2S(s);
    }

    SRC_DATA src_data;
    src_data.data_in = resample_in;
    src_data.input_frames = resample_buf_samples;
    src_data.data_out = &resample_out[resample_out_buf_samples];
    src_data.output_frames = PCM16_B2S(AUDIO_BUFFER_SIZE);
    src_data.src_ratio = ratio;
    src_data.end_of_input = 0;

    int src_err = src_process(resample_state, &src_data);
    if (src_err) {
      DBG("resample error: '%s'\n", src_strerror(src_err));
    }else {
      signed short* samples_s = (signed short*)(unsigned char*)samples;
      resample_out_buf_samples += src_data.output_frames_gen;
      s *= ratio;
      src_float_to_short_array(resample_out, samples_s, PCM16_B2S(s));
      DBG("resample: output_frames_gen = %ld", src_data.output_frames_gen);

      if (resample_buf_samples !=  (unsigned int)src_data.input_frames_used) {
	memmove(resample_in, &resample_in[src_data.input_frames_used],
		(resample_buf_samples - src_data.input_frames_used) * sizeof(float));
      }
      resample_buf_samples = resample_buf_samples - src_data.input_frames_used;

      if (resample_out_buf_samples != s) {
	memmove(resample_out, &resample_out[PCM16_B2S(s)], (resample_out_buf_samples - PCM16_B2S(s)) * sizeof(float));
      }
      resample_out_buf_samples -= PCM16_B2S(s);
    }
  }

  DBG("resample: output size is %d", s);
  return s;
}
Exemplo n.º 15
0
/* 
   @param wallclock_ts [in]    the current ts in the audio buffer 
*/
int AmRtpAudio::receive(unsigned long long system_ts) 
{
  int size;
  unsigned int rtp_ts;
  int new_payload = -1;

  if(!fmt.get() || (!playout_buffer.get())) {
    DBG("audio format not initialized\n");
    return RTP_ERROR;
  }

  unsigned int wallclock_ts = scaleSystemTS(system_ts);

  while(true) {
    size = AmRtpStream::receive((unsigned char*)samples,
				(unsigned int)AUDIO_BUFFER_SIZE, rtp_ts,
				new_payload);
    if(size <= 0) {

      switch(size){

      case 0: break;
	
      case RTP_DTMF:
      case RTP_UNKNOWN_PL:
      case RTP_PARSE_ERROR:
        continue;

      case RTP_TIMEOUT:
        //FIXME: postRequest(new SchedRequest(AmMediaProcessor::RemoveSession,s));
        // post to the session (FIXME: is session always set? seems to be...)
        session->postEvent(new AmRtpTimeoutEvent());
        return -1;

      case RTP_BUFFER_SIZE:
      default:
        ERROR("AmRtpStream::receive() returned %i\n",size);
        //FIXME: postRequest(new SchedRequest(AmMediaProcessor::ClearSession,s));
        //       or AmMediaProcessor::instance()->clearSession(session);
        return -1;
        break;
      }
      
      break;
    }

    if (// don't process if we don't need to
	// ignore CN
	COMFORT_NOISE_PAYLOAD_TYPE == new_payload  ||
	// ignore packet if payload not found
	setCurrentPayload(new_payload)
	){
      playout_buffer->clearLastTs();
      continue;
    }

    size = decode(size);
    if(size <= 0){
      ERROR("decode() returned %i\n",size);
      return -1;
    }

    // This only works because the possible ratio (Rate/TSRate)
    // is 2. Rate and TSRate are only different in case of g722.
    // For g722, TSRate=8000 and Rate=16000
    //
    AmAudioRtpFormat* rtp_fmt = (AmAudioRtpFormat*)fmt.get();
    unsigned long long adjusted_rtp_ts = rtp_ts;

    if(rtp_fmt->getRate() != rtp_fmt->getTSRate()) {
      adjusted_rtp_ts =
	(unsigned long long)rtp_ts *
	(unsigned long long)rtp_fmt->getRate()
	/ (unsigned long long)rtp_fmt->getTSRate();
    }

    playout_buffer->write(wallclock_ts, adjusted_rtp_ts,
			  (ShortSample*)((unsigned char *)samples),
			  PCM16_B2S(size), begin_talk);

    if(!active) {
      DBG("switching to active-mode\t(ts=%u;stream=%p)\n",
	  rtp_ts,this);
      active = true;
    }
  }
  return size;
}