<commit_before>/*
 * L16pay: RTP-playloader for L16
 *
 * (c) 2013 <NAME>, institute of electronic music and acoustics (iem)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "iemrtp.h"

static t_class *L16pay_class;

typedef struct _L16pay
{
	t_object x_obj;
  t_sample**x_in;
  u_int8 x_running;
  u_int32 x_channels;  // number of channels
  u_int32 x_vecsize;   // Pd's blocksize
  u_int32 x_mtu;       // MTU of the socket

  t_rtpheader  x_rtpheader; // the RTP-header
  u_int32 x_rtpheadersize; // the size of the RTP-header

  /* buffer to store the bytes into */
  u_int8*x_buffer;
  u_int32 x_buffersize;

  /* buffer for outputting bytes as list */
  t_atom*x_atombuffer;
  u_int32 x_atombuffersize;
  t_clock*x_clock;

  /* packetizing */
  u_int32 x_payload;
} t_L16pay;

static void L16pay_preparePacket(t_L16pay*x) {
  u_int32 payload; // number of bytes in a single block

  payload=x->x_channels * x->x_vecsize * RTP_BYTESPERSAMPLE; // number of bytes in a single block

  /* get buffer for payload */
  if(x->x_buffersize<payload) {
    if(x->x_buffer)freebytes(x->x_buffer, x->x_buffersize);
    x->x_buffersize=payload;
    x->x_buffer = getbytes(x->x_buffersize);
  }
  x->x_payload=payload;

  if(x->x_atombuffersize < x->x_mtu) {
    u_int32 i;
    if(x->x_atombuffer)
      freebytes(x->x_atombuffer, x->x_atombuffersize * sizeof(t_atom));
    x->x_atombuffersize = x->x_mtu;
    x->x_atombuffer = getbytes(x->x_atombuffersize * sizeof(t_atom));

    // initialize the buffers with floats,
    // so we don't have to repeatedly set the atomtype later
    for(i=0; i<x->x_atombuffersize; i++) {
      SETFLOAT(x->x_atombuffer+i, 0);
    }
  }
  post("\tbufsize: %d", x->x_atombuffersize);
}


/* ******************************************************************************** */
/*                          the work                krow eht                        */
/* ******************************************************************************** */


static t_int *L16pay_perform(t_int *w)
{
  const t_sample scale = 0x7FFF / 1.f;
	t_L16pay* x = (t_L16pay*)(w[1]);
  u_int32 n, vecsize = x->x_vecsize;
  u_int32 c, channels=x->x_channels;
  t_sample**ins=x->x_in;
  u_int8*buffer=x->x_buffer;

  if(!x->x_running)return(w+2);

  for(n=0; n<vecsize; n++) {
    for (c=0;c<channels;c++) {
      // LATER: if(in>1.f) this returns "-1"
      signed short s = ins[c][n] * scale;
      *buffer++=(s>>8) & 0xFF;
      *buffer++=(s>>0) & 0xFF;
    }
  }
  clock_delay(x->x_clock, 0);
	return(w+2);
}

static void L16pay_tick(t_L16pay *x) {      /* callback function for the clock */
  u_int8*buffer=x->x_buffer;
  int payload=x->x_payload;
  u_int32 mtu = x->x_mtu;
  u_int32 channels = x->x_channels;

  while(payload>0) {
    u_int32 headersize;
    u_int32 packetsize;
    u_int32 frames;
    t_atom*ap;
    u_int32 j;

    headersize=header2atoms(&x->x_rtpheader, x->x_atombuffer);
    x->x_rtpheadersize=headersize;

    /* 1st guess at headersize */
    packetsize  = mtu - headersize;
    if(packetsize > (u_int32)payload) {
      /* last packet */
      packetsize = payload;
    } else {
      /* don't fill the packet to the rim (so give some bytes extra) */
      if(packetsize>EMPTYPACKETBYTES*2) packetsize-=EMPTYPACKETBYTES;
    }
    /* number of frames fitting into a package */
    frames=packetsize / (channels * RTP_BYTESPERSAMPLE);
    /* actual packetsize, with full frames */
    packetsize = frames * (channels * RTP_BYTESPERSAMPLE);

    if(packetsize<1) {
      pd_error(x, "oops, empty packet...");
      return;
    }

    ap=x->x_atombuffer + headersize;
    for(j=0; j<packetsize; j++) {
      ap[j].a_w.w_float=*buffer++;
    }
    outlet_list(x->x_obj.ob_outlet, &s_list, headersize+packetsize, x->x_atombuffer);

    x->x_rtpheader.seq += 1;
    x->x_rtpheader.ts  += frames;
    x->x_rtpheader.m    = 0;

    payload-=packetsize;
  }
}


/* ---------------------- Setup junk -------------------------- */

static void L16pay_dsp(t_L16pay *x, t_signal **sp)
{
  u_int32 c;

  x->x_vecsize=sp[0]->s_n;
  x->x_rtpheader.m    = 1;

  L16pay_preparePacket(x);

  for(c=0; c<x->x_channels; c++) {
    x->x_in[c]=sp[c]->s_vec;
  }

  dsp_add(L16pay_perform, 1, x);
}

static void L16pay_MTU(t_L16pay *x, t_floatarg f)
{<commit_msg>increment timestamp in DSP<commit_after>/*
 * L16pay: RTP-playloader for L16
 *
 * (c) 2013 <NAME>, institute of electronic music and acoustics (iem)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "iemrtp.h"

static t_class *L16pay_class;

typedef struct _L16pay
{
	t_object x_obj;
  t_sample**x_in;
  u_int8 x_running;
  u_int32 x_channels;  // number of channels
  u_int32 x_vecsize;   // Pd's blocksize
  u_int32 x_mtu;       // MTU of the socket

  t_rtpheader  x_rtpheader; // the RTP-header
  u_int32 x_rtpheadersize; // the size of the RTP-header

  /* buffer to store the bytes into */
  u_int8*x_buffer;
  u_int32 x_buffersize;

  /* buffer for outputting bytes as list */
  t_atom*x_atombuffer;
  u_int32 x_atombuffersize;
  t_clock*x_clock;

  /* packetizing */
  u_int32 x_payload;
} t_L16pay;

static void L16pay_preparePacket(t_L16pay*x) {
  u_int32 payload; // number of bytes in a single block

  payload=x->x_channels * x->x_vecsize * RTP_BYTESPERSAMPLE; // number of bytes in a single block

  /* get buffer for payload */
  if(x->x_buffersize<payload) {
    if(x->x_buffer)freebytes(x->x_buffer, x->x_buffersize);
    x->x_buffersize=payload;
    x->x_buffer = getbytes(x->x_buffersize);
  }
  x->x_payload=payload;

  if(x->x_atombuffersize < x->x_mtu) {
    u_int32 i;
    if(x->x_atombuffer)
      freebytes(x->x_atombuffer, x->x_atombuffersize * sizeof(t_atom));
    x->x_atombuffersize = x->x_mtu;
    x->x_atombuffer = getbytes(x->x_atombuffersize * sizeof(t_atom));

    // initialize the buffers with floats,
    // so we don't have to repeatedly set the atomtype later
    for(i=0; i<x->x_atombuffersize; i++) {
      SETFLOAT(x->x_atombuffer+i, 0);
    }
  }
  post("\tbufsize: %d", x->x_atombuffersize);
}


/* ******************************************************************************** */
/*                          the work                krow eht                        */
/* ******************************************************************************** */


static t_int *L16pay_perform(t_int *w)
{
  const t_sample scale = 0x7FFF / 1.f;
	t_L16pay* x = (t_L16pay*)(w[1]);
  u_int32 n, vecsize = x->x_vecsize;
  u_int32 c, channels=x->x_channels;
  t_sample**ins=x->x_in;
  u_int8*buffer=x->x_buffer;

  x->x_rtpheader.ts  += vecsize;
  if(!x->x_running)return(w+2);

  for(n=0; n<vecsize; n++) {
    for (c=0;c<channels;c++) {
      // LATER: if(in>1.f) this returns "-1"
      signed short s = ins[c][n] * scale;
      *buffer++=(s>>8) & 0xFF;
      *buffer++=(s>>0) & 0xFF;
    }
  }
  clock_delay(x->x_clock, 0);
	return(w+2);
}

static void L16pay_tick(t_L16pay *x) {      /* callback function for the clock */
  u_int8*buffer=x->x_buffer;
  int payload=x->x_payload;
  u_int32 mtu = x->x_mtu;
  u_int32 channels = x->x_channels;

  while(payload>0) {
    u_int32 headersize;
    u_int32 packetsize;
    u_int32 frames;
    t_atom*ap;
    u_int32 j;

    headersize=header2atoms(&x->x_rtpheader, x->x_atombuffer);
    x->x_rtpheadersize=headersize;

    /* 1st guess at headersize */
    packetsize  = mtu - headersize;
    if(packetsize > (u_int32)payload) {
      /* last packet */
      packetsize = payload;
    } else {
      /* don't fill the packet to the rim (so give some bytes extra) */
      if(packetsize>EMPTYPACKETBYTES*2) packetsize-=EMPTYPACKETBYTES;
    }
    /* number of frames fitting into a package */
    frames=packetsize / (channels * RTP_BYTESPERSAMPLE);
    /* actual packetsize, with full frames */
    packetsize = frames * (channels * RTP_BYTESPERSAMPLE);

    if(packetsize<1) {
      pd_error(x, "oops, empty packet...");
      return;
    }

    ap=x->x_atombuffer + headersize;
    for(j=0; j<packetsize; j++) {
      ap[j].a_w.w_float=*buffer++;
    }
    outlet_list(x->x_obj.ob_outlet, &s_list, headersize+packetsize, x->x_atombuffer);

    x->x_rtpheader.seq += 1;
    x->x_rtpheader.m    = 0;

    payload-=packetsize;
  }
}


/* ---------------------- Setup junk -------------------------- */

static void L16pay_dsp(t_L16pay *x, t_signal **sp)
{
  u_int32 c;

  x->x_vecsize=sp[0]->s_n;
  x->x_rtpheader.m    = 1;

  L16pay_preparePacket(x);

  for(c=0; c<x->x_channels; c++) {
    x->x_in[c]=sp[c]->s_vec;
  }

  dsp_add(L16pay_perform, 1, x);
}

static void L16pay_MTU(t_L16pay *x, t_floatarg f)
{
{'fraction_non_alphanumeric': 0.167926455566905, 'fraction_numerical': 0.022880490296220635, 'mean_word_length': 3.0863939899833057, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 117, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4340877', 'n_tokens_mistral': 3813, 'n_tokens_neox': 3644, 'n_words': 845}