예제 #1
0
/**
 * Contiguous Fetch.
 * The simple API is blocking, which is perfect for tracter.  Fab.
 */
Tracter::SizeType
Tracter::PulseAudioSource::ContiguousFetch(
    IndexType iIndex, SizeType iLength, SizeType iOffset
)
{
    if (mMaxIndex)
        if (iIndex > mMaxIndex)
            return 0;

    /* I'm assuming that it reads a whole buffer-full here */
    int error;
    int ret = pa_simple_read(
        mHandle,
        GetPointer(iOffset),
        iLength * sizeof(float),
        &error
    );
    if (ret < 0)
        throw Exception("%s: Failed to read %d samples. %s",
                        mObjectName, iLength, pa_strerror(error));

    if (mMaxIndex)
        if (iIndex + iLength > mMaxIndex)
            return mMaxIndex - iIndex;
    return iLength;
}
예제 #2
0
파일: capture.c 프로젝트: cshengqun/raop
int main(int argc, char*argv[]) {
    /* The sample type to use */
    static const pa_sample_spec ss = {
        .format = PA_SAMPLE_S16LE,
        .rate = 44100,
        .channels = 2
    };
    pa_simple *s = NULL;
    int ret = 1;
    int error;
    /* Create the recording stream */
    if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
        fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
        goto finish;
    }
    for (;;) {
        uint8_t buf[BUFSIZE];
        /* Record some data ... */
        if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) {
            fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
            goto finish;
        }
        /* And write it to STDOUT */
        if (loop_write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) {
            fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno));
            goto finish;
        }
    }
    ret = 0;
finish:
    if (s)
        pa_simple_free(s);
    return ret;
}
예제 #3
0
void MediaRecorder::RecordingThread()
{
    int error;
    while ( run )
    {

        printf("Read %d samples\n",actx->frame_size*2);
        short * buf = new short[actx->frame_size*2];
        int ret = pa_simple_read(s,buf,actx->frame_size*4,&error);
        if ( ret < 0 )
        {
            printf("Sound crashed\n");
            delete[] buf;
            break;
        }
        for ( int i = 0; i < actx->frame_size*2; i++ )
        {
            buf[i] = short(float(buf[i])*0.8);
        }
        fwrite(buf,sizeof(short)*actx->frame_size*2,1,debug_samples_out);
        pthread_mutex_lock(&sound_buffer_lock);
        sound_buffers.push_back(buf);
        pthread_mutex_unlock(&sound_buffer_lock);
    }
}
예제 #4
0
파일: sound.c 프로젝트: padsof-uam/redes2
int _recordSound(char *buf, int size)
{
    int error;

    if (pa_simple_read(sr, buf, (size_t) size, &error) < 0) return error;
    return 0;
}
예제 #5
0
static void *pulse_audio_update_recorder(ALLEGRO_THREAD *t, void *data)
{
   ALLEGRO_AUDIO_RECORDER *r = (ALLEGRO_AUDIO_RECORDER *) data;
   PULSEAUDIO_RECORDER *pa = (PULSEAUDIO_RECORDER *) r->extra;
   ALLEGRO_EVENT user_event;
   uint8_t *null_buffer;
   unsigned int fragment_i = 0;
   
   null_buffer = al_malloc(1024);
   if (!null_buffer) {
      ALLEGRO_ERROR("Unable to create buffer for draining PulseAudio.\n");
      return NULL;
   }
   
   while (!al_get_thread_should_stop(t))
   {
      al_lock_mutex(r->mutex);
      if (!r->is_recording) {
         /* Even if not recording, we still want to read from the PA server.
            Otherwise it will buffer everything and spit it all out whenever
            the recording resumes. */
         al_unlock_mutex(r->mutex);
         pa_simple_read(pa->s, null_buffer, 1024, NULL);
      }
      else {
         ALLEGRO_AUDIO_RECORDER_EVENT *e;
         al_unlock_mutex(r->mutex);
         if (pa_simple_read(pa->s, r->fragments[fragment_i], r->fragment_size, NULL) >= 0) {
            user_event.user.type = ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT;
            e = al_get_audio_recorder_event(&user_event);
            e->buffer = r->fragments[fragment_i];
            e->samples = r->samples;           
            al_emit_user_event(&r->source, &user_event, NULL);
         
            if (++fragment_i == r->fragment_count) {
               fragment_i = 0;
            }
         }
      }
   }

   al_free(null_buffer);
   return NULL;
};
예제 #6
0
bool
ManglerPulse::read(uint8_t *buf) {/*{{{*/
    if (!pulse_stream) {
        return false;
    }
    if (pa_simple_read(pulse_stream, buf, buffer_attr.fragsize, &pulse_error) < 0) {
        fprintf(stderr, "pulse: pa_simple_read() failed: %s\n", pa_strerror(pulse_error));
        return false;
    }
    return true;
}/*}}}*/
예제 #7
0
static int pulse_input(struct iaxc_audio_driver *d, void *samples, int *nSamples)
{
  
  int error;
  pa_simple *p = (pa_simple*)(d->priv);
  if(pa_simple_read(p, samples, *nSamples*sizeof(short) , &error) <0)
  {
    fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
  }
  // always return 0, since pulse gives us a continuos stream of data
  return 0;
}
예제 #8
0
int pulseaudio_read(pa_simple *s, short *buffer, int count){
	int number_read;
	int channels;
	if (sound_channels == SOUND_CHANNELS_MONO)
		channels = 1;
	else
		channels = 2;
	number_read = pa_simple_read(s,buffer,(size_t)(count * sizeof(short) * channels) ,NULL);
	if(number_read < 0)
		return -1;
	return count; 
}
예제 #9
0
static void input_sound(unsigned int sample_rate, unsigned int overlap,
                        const char *ifname)
{

    short buffer[8192];
    float fbuf[16384];
    unsigned int fbuf_cnt = 0;
    int i;
    int error;
    short *sp;

    // Init stuff from pa.org
    pa_simple *s;
    pa_sample_spec ss;

    ss.format = PA_SAMPLE_S16NE;
    ss.channels = 1;
    ss.rate = sample_rate;


    /* Create the recording stream */
    if (!(s = pa_simple_new(NULL, "multimonNG", PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
        fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
        exit(4); 
    }

    for (;;) {
        i = pa_simple_read(s, sp = buffer, sizeof(buffer), &error);
        if (i < 0 && errno != EAGAIN) {
            perror("read");
            fprintf(stderr, "error 1\n");
            exit(4);
        }
        i=sizeof(buffer);
        if (!i)
            break;

        if (i > 0) {
            for (; i >= sizeof(buffer[0]); i -= sizeof(buffer[0]), sp++)
                fbuf[fbuf_cnt++] = (*sp) * (1.0/32768.0);
            if (i)
                fprintf(stderr, "warning: noninteger number of samples read\n");
            if (fbuf_cnt > overlap) {
                process_buffer(fbuf, fbuf_cnt-overlap);
                memmove(fbuf, fbuf+fbuf_cnt-overlap, overlap*sizeof(fbuf[0]));
                fbuf_cnt = overlap;
            }
        }
    }
    pa_simple_free(s);
}
예제 #10
0
bool vis::PulseAudioSource::read(pcm_stereo_sample *buffer,
                                 const uint32_t buffer_size)
{
    size_t buffer_size_bytes =
        static_cast<size_t>(sizeof(pcm_stereo_sample) * buffer_size);

#ifdef _ENABLE_PULSE

    if (m_pulseaudio_simple == nullptr)
    {
        open_pulseaudio_source(static_cast<uint32_t>(buffer_size_bytes));
    }

    if (m_pulseaudio_simple != nullptr)
    {
        // zero out buffer
        memset(buffer, 0, buffer_size_bytes);

        int32_t error_code;
        /* Record some data ... */
        auto return_code = pa_simple_read(m_pulseaudio_simple, buffer,
                                          buffer_size_bytes, &error_code);

        if (return_code < 0)
        {
            VIS_LOG(vis::LogLevel::WARN, "Could not finish reading pulse audio "
                                         "stream buffer, bytes read: %d buffer "
                                         "size: ",
                    return_code, buffer_size_bytes);

            // zero out buffer
            memset(buffer, 0, buffer_size_bytes);

            pa_simple_free(m_pulseaudio_simple);
            m_pulseaudio_simple = nullptr;

            return false;
        }

        // Success fully read entire buffer
        return true;
    }
#endif
    // zero out buffer
    memset(buffer, 0, buffer_size_bytes);

    return false;
}
예제 #11
0
void init(void)
{
   int error;
   
   /* The sample type to use */
   static const pa_sample_spec ss = {
      .format = PA_SAMPLE_S16NE, // signed 16bits , Native endian
      .rate = 44100,
      .channels = 1
   };
   
   /* Create the recording stream */
   if (!(s = pa_simple_new(NULL, "USB VUmeter", PA_STREAM_RECORD, DEVICE, "record", &ss, NULL, NULL, &error))) {
      fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
   }
   printf("%d\n",sizeof(short));
}

float value (void)
{
   int error;
   uint8_t buf[BUFSIZE];
   int16_t *pbuf = (int16_t*)buf; // 16bit signed
   float percent;
   static double max_level=0, min_level=10000;
   double nrj=0;
         
   /* Record some data ... */
   if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) {
      fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
   }

   while (pbuf < (int16_t*)buf+sizeof(buf))
   {
      nrj += (*pbuf) * (*pbuf);
      pbuf++;
//       printf("%02X ",buf[i]);
   }
   nrj = sqrt(nrj)/(sizeof(buf));
   if(nrj > max_level)
      max_level = nrj;
   if(nrj < min_level)
      min_level = nrj;
   percent = (float) 100 * (nrj-min_level) / (max_level-min_level);
//    printf ("min:%f, nrj:%f, max:%f, %%:%f\n",min_level, nrj, max_level, nrj / max_level);
   
   return percent;
}
예제 #12
0
파일: i_pulse.c 프로젝트: Jheengut/gmerlin
static gavl_source_status_t read_func_pulse(void * p, gavl_audio_frame_t ** frame)
  {
  bg_pa_t * priv;
  int error = 0;

  gavl_audio_frame_t * f = *frame;
  
  priv = p;
  if(pa_simple_read(priv->pa, f->samples.u_8,
                    priv->block_align * priv->format.samples_per_frame,
                    &error) < 0)
    {
    return GAVL_SOURCE_EOF;
    }
  f->valid_samples = priv->format.samples_per_frame;
  return GAVL_SOURCE_OK;
  }
예제 #13
0
int32
ad_read(ad_rec_t * r, int16 * buf, int32 max)
{
    int error;

    if (!r->recording)
	return AD_EOF;
	
	if (max > 2048) {
	    max = 2048;
    }
	
    if (pa_simple_read(r->pa, (void*)buf, max * 2, &error) < 0) {
	fprintf(stderr, "Failed to read speech: %s\n", pa_strerror(error));
    }
    
    return max;
}
예제 #14
0
static ssize_t
pulse_read (sw_handle * handle, float * buf, size_t count)
{
  struct pa_simple * pa ;
  int error;
  size_t byte_count;

  if ((pa = (struct pa_simple *)handle->custom_data) == NULL)
    return 0;

  byte_count = count * sizeof (float);

  if (pa_simple_read(pa, buf, byte_count, &error) < 0) {
    fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
    return 0;
  }
  return 1;
}
예제 #15
0
int main(int argc, char*argv[]) {
	/* The sample type to use */
	static const pa_sample_spec ss = {
		.format = PA_SAMPLE_S16LE,
		.rate = 44100,
		.channels = 2
	};
	pa_simple *inStream = NULL;
	pa_simple *outStream = NULL;

	int ret = 1;
	int error;
	/* Create the recording stream */
	if (!(inStream = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
		fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
		goto finish;
	}
	/* Create the playback stream */
	if (!(outStream = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error))) {
		fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
		goto finish;
	}
	for (;;) {
		uint8_t buf[BUFSIZE];
		/* Record some data ... */
		if (pa_simple_read(inStream, buf, sizeof(buf), &error) < 0) {
			fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
			goto finish;
		}
		if (pa_simple_write(outStream, buf, sizeof(buf), &error) < 0) {
			fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error));
			goto finish;
		}
	}
	ret = 0;
	finish:
	if (inStream)
		pa_simple_free(inStream);
	if (outStream)
		pa_simple_free(outStream);
	return ret;
}
예제 #16
0
파일: main.c 프로젝트: pt300/paSpec
struct pa_simple *pulseaudio_begin(void) {
    int error;
    struct pa_simple *s;

    static const pa_sample_spec ss = {
        .format = PA_SAMPLE_FLOAT32LE,
        .rate = RATE,
        .channels = 1
    };
    static const pa_buffer_attr sb = {
        .maxlength = N * 2,
        .fragsize = N * 2
    };
    if(!(s = pa_simple_new(NULL, "paSpec", PA_STREAM_RECORD, NULL, "input stream", &ss, NULL, &sb, &error))) {
        printf("Error: pulseaudio: pa_simple_new() failed: %s\n", pa_strerror(error));
        clean_screen();
        exit(1);
    }
    return s;
}

void pulseaudio_end(struct pa_simple *s) {
    if(s != NULL) {
        pa_simple_free(s);
    }
}

void pulseaudio_read(struct pa_simple *s, float *buf, int sampnum) {
    int error;
    if(pa_simple_read(s, buf, sampnum * sizeof(float), &error) < 0) {
        printf("Error: pa_simple_read() failed: %s\n", pa_strerror(error));
        pulseaudio_end(s);
        exit(1);
    }
}

void prnt(char hah, unsigned int cnt, unsigned int s, unsigned int sh) {
    while(cnt--) {
        printf("\e[%i;%iH%c", sh - cnt, s, hah);
    }
}
예제 #17
0
int
adin_read(SP16 * buf, int sampnum)
{	
	int cnt, bufsize;
	bufsize = sampnum * sizeof(SP16);
	
	if (bufsize > BUFSIZE) bufsize = BUFSIZE;
	
	SP16 inbuf[bufsize];
	
	
	if (pa_simple_read(r, inbuf, bufsize, &errorpa) < 0) {
		printf("Error: adin_pulseaudio: pa_simple_read() failed: %s\n", pa_strerror(errorpa));
		return (-2);
	}
	
	libpd_process_short(4, inbuf, buf);

	cnt = bufsize / sizeof(SP16);
	return(cnt);
}
예제 #18
0
int main(int argc, char *argv[])
{
   pa_simple *pa = NULL;
   pa_sample_spec paspec = { PA_SAMPLE_S16NE, 32000, 1 };
   void *state = NULL;
   SpeexBits bits;
   int quality = 3;
   int complexity = 1;
   int framesize = 0;
   int16_t *framein = NULL;
   char *frameout = NULL;
   int len;

   do {
      if(!(pa = pa_simple_new(NULL, "", PA_STREAM_RECORD, NULL, "", &paspec, NULL, NULL, NULL))) break;
      speex_bits_init(&bits);
      if(!(state = speex_encoder_init(&speex_uwb_mode))) break;
      if(speex_encoder_ctl(state, SPEEX_SET_QUALITY, &quality)) break;
      if(speex_encoder_ctl(state, SPEEX_SET_COMPLEXITY, &complexity)) break;
      if(speex_encoder_ctl(state, SPEEX_GET_FRAME_SIZE, &framesize) || !framesize) break;
      if(!(framein = calloc(framesize, sizeof(int16_t)))) break;
      if(!(frameout = calloc(framesize, sizeof(int16_t)))) break;

      while(1) {
         if(pa_simple_read(pa, framein, framesize * sizeof(int16_t), NULL)) break;
         speex_bits_reset(&bits);
         speex_encode_int(state, framein, &bits);
         if(!(len = speex_bits_write(&bits, frameout, framesize * sizeof(int16_t)))) break;
         fwrite(&len, sizeof(int), 1, stdout);
         fwrite(frameout, 1, len, stdout);
      }
   } while(0);
   if(framein) free(framein);
   if(frameout) free(frameout);
   if(state) speex_encoder_destroy(state);
   speex_bits_destroy(&bits);
   if(pa) pa_simple_free(pa);

   return 0;
}
예제 #19
0
int main()
{
  pa_sample_spec ss;
  ss.format = PA_SAMPLE_S16LE;
  ss.channels = 1;
  ss.rate = 96000;

  pa_buffer_attr ba;
  ba.maxlength = (uint32_t)-1;
  ba.tlength = 0;
  ba.prebuf = (uint32_t)-1;
  ba.minreq = (uint32_t)-1;
  ba.fragsize = (uint32_t)-1;

  pa_simple* s_rec = pa_simple_new(NULL, "echo", PA_STREAM_RECORD, NULL,
                                   "Record", &ss, NULL, &ba, NULL);

  pa_simple* s_play = pa_simple_new(NULL, "echo", PA_STREAM_PLAYBACK, NULL,
                                    "Echo", &ss, NULL, &ba, NULL);

  if (!s_rec) {
    fprintf(stderr, "Pulse rec failed.\n");
    return 1;
  }

  if (!s_play) {
    fprintf(stderr, "Pulse play failed.\n");
    return 1;
  }


  char buffer[sizeof(short) * 128];
  for (;;) {
    pa_simple_read(s_rec, buffer, sizeof(buffer), NULL);
    pa_simple_write(s_play, buffer, sizeof(buffer), NULL);
  }

  return 0;
}
예제 #20
0
파일: shusherd.c 프로젝트: shyPi/shyPi
void audio_trigger(context_t *context) {
  int input_fd = -1;
  static const pa_sample_spec ss = {
    .format = PA_SAMPLE_S16LE,
    .rate = 44100,
    .channels = 1
  };
  int error;

  daemon_log(LOG_INFO, "Trigger %s", context->shush_filename);

  if (context->points_threshold < 0) {
    daemon_log(LOG_INFO, "Threshold below 0, not triggering sound");
  }

  daemon_log(LOG_INFO,
             "Opening %s for output",
             context->output_device ?: "default sink");

  pa_simple *pa_output = pa_simple_new(
                              NULL,
                              "shusherd",
                              PA_STREAM_PLAYBACK,
                              context->output_device,
                              "playback",
                              &ss,
                              NULL,
                              NULL,
                              &error);
  if (!pa_output) {
    daemon_log(LOG_ERR, "pa_simple_new failed: %s", pa_strerror(error));
    goto finish;
  }

  input_fd = open(context->shush_filename, O_RDONLY);
  if (input_fd < 0) {
    daemon_log(LOG_ERR, "Error reading %s: %s", context->shush_filename, strerror(errno));
    goto finish;
  }

  for (;;) {
    uint8_t buf[BUFSIZE];
    ssize_t r;

    r = read(input_fd, buf, sizeof(buf));
    if (r < 0) {
      daemon_log(LOG_ERR, "read() failed: %s", strerror(errno));
      goto finish;
    }

    if (r == 0)
      goto finish;

    if (pa_simple_write(pa_output, buf, (size_t) r, &error) < 0) {
      daemon_log(LOG_ERR, "pa_simple_write() failed: %s", pa_strerror(errno));
      goto finish;
    }
  }

  if (pa_simple_drain(pa_output, &error) < 0) {
    daemon_log(LOG_ERR, "pa_simple_drain() failed: %s", pa_strerror(errno));
    goto finish;
  }

finish:
  if (input_fd > 0)
    close(input_fd);
  if (pa_output)
    pa_simple_free(pa_output);
}

void *audio_loop(void *context_p) {
  context_t *context = (context_t *)context_p;
  time_t t = time(NULL);
  double loudness;
  double points = 0.0;
  int error;

  //pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

  daemon_log(LOG_INFO, "Starting listening...");

  const short buf[BUFSIZE/2];

  int bytes = 0;
  int trigger = 0;
  int latest_trigger_time = 0;

  while (context->enable_processing) {
    if ((bytes = pa_simple_read(context->pa_input, (void *)buf, sizeof(buf), &error)) < 0) {
      daemon_log(LOG_ERR, "pa_simple_read failed: %s", pa_strerror(error));
      assert(0);
    }

    if ((time(NULL) - latest_trigger_time) < context->cooldown) {
      continue;
    }

    ebur128_add_frames_short(context->ebur128_state, buf, sizeof(buf)/2);

    if ((time(NULL) - t) > SAMPLE_TIME) {
      t = time(NULL);
      ebur128_loudness_shortterm(context->ebur128_state, &loudness);

      points += 100 - fabs(loudness);

      daemon_log(LOG_INFO, "Points: %f (%d) (%f)",
                 points, context->points_threshold, loudness);

      if (points > context->points_threshold) {
        trigger = 1;
      } else {
        points *= context->decay;
      }
    }

    if (trigger) {
      latest_trigger_time = time(NULL);
      audio_trigger(context);
      points = 0;
      trigger = 0;
      daemon_log(LOG_INFO,
                 "Waiting %d seconds before listening again",
                 context->cooldown);
    }
  }

  daemon_log(LOG_INFO, "Stopped listening...");

  return 0;
}
예제 #21
0
파일: am.c 프로젝트: flyhorsegit/am
int main(int argc, char **argv) {
    modulation mod = AM;
    int genwav = 0;
    int test = 0;
    int chat = 0;
    static struct option long_options[] = {
        {"modulation",  required_argument, 0, 'm'},
        {"genwav",  no_argument,       0, 'g'},
        {"test",  no_argument,       0, 't'},
        {"chat",  no_argument,       0, 'c'},
        {0, 0, 0, 0}
    };
    int c;
    int option_index = 0;
    do {
        c = getopt_long (argc, argv, "m:gt",
                         long_options, &option_index);
        switch (c) {
        case 0:
            break;
        case 'm':
            if (strcmp(optarg, "AM") == 0) {
                mod = AM;
                break;
            }
            if (strcmp(optarg, "FM") == 0) {
                mod = FM;
                break;
            }
            fprintf(stderr, "Error: Invalid modulation\n");
            return 1;
        case 't':
            test = 1;
            break;
        case 'g':
            genwav = 1;
            break;
        case 'c':
            chat = 1;
            break;
        case -1:
            break;
        default:
            return 1;
            break;
        }
    } while (c != -1);
    if (!(test || chat || genwav)) {
        fprintf(stderr, "Error: You must suply an action\n");
        return 1;
    }


    int *vbuf;
    frame *msg;
    int i;

    if (genwav || test) {
        vbuf = get_fdata(PING_STR, strlen(PING_STR), mod);
        if (chk_wav_data(vbuf, &msg, mod))
            printf("Info: PCM data is ok.\n");
        else {
            fprintf(stderr, "Error: PCM data can not be read\n");
            for (i = 0; i < FRAME_SIZE; i++)
                fprintf(stderr, "%hhx", ((char *) msg)[i]);
            fprintf(stderr, "\n");
        }
    }
    if (genwav) {
        FILE *am = fopen("am.wav", "w");
        if (am == NULL) {
            printf("could not open files\n");
            exit(1);
        }
        write_wav(am, FRAME_BUFFER, vbuf);
        printf("Info: WAV ready\n");
    }

    if (!chat) return 0;

    char *mg  = (char *) malloc(65536);
    int j;
    pa_simple *ch = get_ch();
    pa_simple *pl = get_pl();
    int err = 0;
    int *buf = (int *) malloc(sizeof(int) * SAMPLE_BUFFER);
    sbf = (int *) calloc(sizeof(int), FRAME_BUFFER);
    int *pbf;
    fd_set set;
    int rv;
    struct timeval tv;

    printf("Info: Starting soundwave chat.\n");
    while (1) {
        if (pa_simple_read(ch, buf, sizeof(int) * SAMPLE_BUFFER, &err))
            fprintf(stderr, "Error: %s\n", pa_strerror(err));
        //filter_frq(buf, SAMPLE_BUFFER);
        mmpush(sbf, FRAME_BUFFER * sizeof(int), buf, SAMPLE_BUFFER * sizeof(int));
        msg = get_msg(sbf, mod);
        if (chk_frm(msg)) {
            printf("M: %.*s", 61, msg->data);
            flushfb();
        }
        free(msg);
        FD_ZERO(&set);
        FD_SET(STDIN_FILENO, &set);
        tv.tv_sec = 0;
        tv.tv_usec = 0;
        rv = select(STDIN_FILENO + 1, &set, NULL, NULL, &tv);
        if ((rv != 0) && (rv != -1)) {
            rv = read(STDIN_FILENO, mg, 65536);
            for (i = 0; i < rv; i += 61) {
                j = ((i + 61) <= rv) ? 61 : (rv - i);
                pbf = get_fdata(mg + i, j, mod);
                if (pa_simple_write(pl, pbf, FRAME_BUFFER * sizeof(int), &err))
                    printf("error: %s\n", pa_strerror(err));
                free(pbf);
            }
        }
        fflush(stdin);
        fflush(stdout);
        fflush(stderr);
    }
    printf("\n");
    pa_simple_free(ch);
    pa_simple_free(pl);
    return 0;
}
예제 #22
0
int
main(int argc, char *argv[])
{
    if (argc < 2) {
        exit(1);
    }
    
/*
 *  This didn't work    
 *  see how-to-use-echo-cancellation-module-in-pulseaudio
 *  [http://stackoverflow.com/questions/13363241/
 *  how-to-use-echo-cancellation-module-in-pulseaudio]
 *  setenv("PULSE_PROP", "filter.want=echo-cancel", 1);
 */ 
    
    char data[BUFSIZE];
    ssize_t length = 0;
    memset(data, 0, BUFSIZE);
    
    static const pa_sample_spec pass = {
        .format = PA_SAMPLE_S16LE,
        .rate = 22050,
        .channels = 1
    };
    pa_simple *pas = NULL;
    int error = 0;
    if ((pas = pa_simple_new(NULL, "yyclient", PA_STREAM_RECORD, NULL, "record", &pass, NULL, NULL, &error)) == NULL) {
        fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
        if (pas) {
            pa_simple_free(pas);
        }
        exit(error);
    }
    
    int socket_fd;
    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("server socket error");
        exit(1);
    }
    
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    if(inet_pton(AF_INET, argv[1], &server_addr.sin_addr) <= 0){
        perror("inet_pton errno");
        close(socket_fd);
        exit(1);
    }
    server_addr.sin_port = htons(PORT);
    
    int connect_fd;
    if ((connect_fd = connect(socket_fd, (struct sockaddr*) &server_addr, sizeof(server_addr))) == -1) {
        perror("connect error");
        close(socket_fd);
        exit(1);
    }
    
    do {
         if (pa_simple_read(pas, data, BUFSIZE, &error) < 0) {
            fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
            if (pas) {
                pa_simple_free(pas);
            }
            close(connect_fd);
            close(socket_fd);
            exit(error);
        }
    } while ((length = send(socket_fd, data, BUFSIZE, 0)) == BUFSIZE);
    
    if (length == -1) {
        perror("send error");
        close(connect_fd);
        close(socket_fd);
        exit(errno);
    }
    
    close(connect_fd);
    close(socket_fd);
    
    exit(0);
}
예제 #23
0
int pulseaudio_read(pa_simple *s, short *buffer, int count, unsigned char channels_number){
    int number_read = pa_simple_read(s, buffer, (size_t)(count * sizeof(short) * channels_number), NULL);
    return (number_read < 0) ? -1 : count;
}
예제 #24
0
int main(int argc ,char **argv)
{
	if(argc != 2)
	{
		av_log(":Usage: %s <index> \n",argv[0]);
		return -1;
	}

	m_index = atoi(argv[1]);

	av_log("AudioRecoder start ... \n");
	av_log("AudioRecoder version %s\n",version_str);
	av_log("AudioRecoder index %d\n",m_index);


	int m_samplesSize = 4608;
	int16_t *m_AudioBuff = (int16_t*)calloc(m_samplesSize,sizeof(int16_t));
	if(m_AudioBuff == NULL)
	{
		av_log("AudioRecord : calloc m_AudioBuff failed\n");
	   	return -2;
	}

	int fd_fifo;
	char pipename[32] = {0};
	
	sprintf(pipename, "/tmp/pulse-00%d", m_index); 
	if((mkfifo(pipename, O_CREAT|O_RDWR|0777)) && (errno != EEXIST))  
	{
		av_log("AudioRecord : mkfifo pipe failed: errno=%d\n",errno);
		return -3;
	}  
#if 1
	if((fd_fifo = open(pipename, O_RDWR)) < 0)  
	{  
		av_log("AudioRecord : open pipe failed: errno=%d\n",errno);
		return -4; 
	}
#endif

#if DUMP
	int fd_dump;
	char dump_filename[64];

	sprintf(dump_filename, "/tmp/dump00%d.pcm", m_index);
	if((fd_dump = open(dump_filename, O_RDWR|O_CREAT|O_TRUNC)) < 0)  
	{  
		av_log("AudioRecord : open dump_filename failed: errno=%d\n",errno);
		return -5; 
	}
#endif
	

    vdm_init(&vdm_main,m_index);


    pa_simple* m_pReadStream;
    pa_sample_spec m_paSample;
    
	/*m_paSample = {PA_SAMPLE_S16LE, 48000, 2};*/
	m_paSample.format = PA_SAMPLE_S16LE;
	m_paSample.rate = 48000;
	m_paSample.channels = 2;
	
	int pa_error;
	char monitorname[32];
	int pa_index = m_index % 8;
	
	if (pa_index == 0)
		pa_index = 8;
	sprintf(monitorname,"%d.monitor",pa_index);
	
	/* Create the recording stream */
	m_pReadStream = pa_simple_new(NULL,NULL, PA_STREAM_RECORD, monitorname, "record", &m_paSample, NULL, NULL, &pa_error);
	if (!m_pReadStream) 
	{
	   av_log("AudioRecord : pa_simple_new() failed: %s\n", pa_strerror(pa_error));
	   return -6;
	}

	av_log("AudioRecoder start pa_simple_read... \n");


    char audmixedbuf[4608];

    char audbuf[4608];
    int audlen=sizeof audbuf;
    uint64_t ts;

	while(1)
	{
	    av_log("AudioRecord : pa_simpel_read(4608) \n");
//		memset(m_AudioBuff,0,m_samplesSize*sizeof(int16_t));
	    if (pa_simple_read(m_pReadStream, (uint8_t*)m_AudioBuff,m_samplesSize, &pa_error) < 0) 
		{
	    	av_log("AudioRecord : pa_simple_read() failed: %s\n", pa_strerror(pa_error));
	       	return -7;
	    }
	        av_log("AudioRecord : pa_simpel_read(4608)-0-0 \n");
#if 1
	    if((write(fd_fifo,(uint8_t*)m_AudioBuff,m_samplesSize)) < 0)  
	    {  
	        av_log("AudioRecord : write() failed\n");
	       	return -8;  
	    }
#else

        vdm_check_audiofragment(&vdm_main);
	        av_log("AudioRecord : pa_simpel_read(4608)-1-1 \n");

        videosurf*vs=NULL;
        audiofrag*af=NULL;

        VDM_FOREACH_BEGIN(&vdm_main,vs,af)

            audlen=4608;
            if(_i==0){
//                shmaudio_get(af,audmixedbuf,&audlen,&ts);
                continue;
            }else{
//                shmaudio_get(af,audbuf,&audlen,&ts);
                //mix here
//                pcm_mix_16_ch2((int16_t*)audmixedbuf,(int16_t*)audbuf,audlen);
            }

        VDM_FOREACH_END

        memcpy(m_AudioBuff,audmixedbuf,4608);

	    av_log("AudioRecord : pa_simpel_read(4608)--== \n");
	    write(fd_fifo,(uint8_t*)m_AudioBuff,m_samplesSize);
#endif
		
#if DUMP
		if((write(fd_dump,(uint8_t*)m_AudioBuff,m_samplesSize)) < 0)  
	    {  
	        av_log("AudioRecord : write() fd_dump failed\n");
	       	return -9;  
	    }
#endif

	}

	
	free(m_AudioBuff);
	close(fd_fifo);
#if DUMP
	close(fd_dump);
#endif
	pa_simple_free(m_pReadStream);

	av_log("AudioRecoder end ... \n");
	fclose(fp_log);
	
    vdm_fini(&vdm_main);


	return 0;
	
}
예제 #25
0
int
main (int argc, char *argv[])
{
  /* Accept the users's choice of hosts or use the default.  Then do
    the same for the TCP/IP port at which the server is listening as
    well as the number of iterations to perform.  */
  const char *server_host = argc > 1 ? argv[1] : SERVER_HOST;
  u_short server_port = argc > 2 ? ACE_OS::atoi (argv[2]) : SERVER_PORT;
  int max_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : MAX_ITERATIONS;

  /* Build ourselves a Stream socket. This is a connected socket that
    provides reliable end-to-end communications. We will use the
    server object to send data to the server we connect to.  */


  /* And we need a connector object to establish that connection. The
    ACE_SOCK_Connector object provides all of the tools we need to
    establish a connection once we know the server's network
    address...  */
  ACE_SOCK_Connector connector;

  /* Which we create with an ACE_INET_Addr object. This object is
    given the TCP/IP port and hostname of the server we want to
    connect to.  */
  ACE_INET_Addr addr (server_port,
                      server_host);

  /* So, we feed the Addr object and the Stream object to the
    connector's connect() member function. Given this information, it
    will establish the network connection to the server and attach
    that connection to the server object.  */
  if (connector.connect (server, addr) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p\n",
                       "open"),
                      -1);

  /* Just for grins, we'll send the server several messages.  */
  pa_sample_spec capture_profile;
  capture_profile.channels = 1;
  capture_profile.rate = 44100;
  capture_profile.format = PA_SAMPLE_S16LE;

  int error;

  pa_simple *paCaptureHandle = pa_simple_new(NULL,"soundCard", PA_STREAM_RECORD, NULL, "record", &capture_profile, NULL, NULL, &error);

  omni_thread* read = new omni_thread(read_thread, (void *)&max_iterations );
  read->start();



  for (int i = 0; i < max_iterations; i++)
    {
      short buffer[2048];

      /* Create our message with the message number */
      pa_simple_read(paCaptureHandle, buffer, 2048, &error);
     // sprintf((char*)buffer,"Message = %d\n",i);
      /* Send the message to the server.  We use the server object's
        send_n() function to send all of the data at once. There is
        also a send() function but it may not send all of the
        data. That is due to network buffer availability and such. If
        the send() doesn't send all of the data, it is up to you to
        program things such that it will keep trying until all of the
        data is sent or simply give up. The send_n() function already
        does the "keep trying" option for us, so we use it.

        Like the send() method used in the servers we've seen, there
        are two additional parameters you can use on the send() and
        send_n() method calls.  The timeout parameter limits the
        amount of time the system will attempt to send the data to the
        peer.  The flags parameter is passed directly to the OS send()
        system call.  See send(2) for the valid flags values.  */
      if (server.send_n (buffer,2048) == -1)
        //ACE_ERROR_RETURN ((LM_ERROR,
        //                   "%p\n",
        //                   "send"),
        //                  -1);
      //else
        /* Pause for a second.  */
       // ACE_OS::sleep (1);
    	  memset(buffer,2048,0);

    }
  pa_simple_free(paCaptureHandle);
  /* Close the connection to the server.  The servers we've created so
    far all are based on the ACE_Reactor.  When we close(), the
    server's reactor will see activity for the registered event
    handler and invoke handle_input().  That, in turn, will try to
    read from the socket but get back zero bytes.  At that point, the
    server will know that we've closed from our side.  */
  while(read->state()!=omni_thread::STATE_TERMINATED);
  if (server.close () == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p\n",
                       "close"),
                      -1);
  return 0;
}
예제 #26
0
파일: sound.c 프로젝트: OSgenie/xrdp
static void *DEFAULT_CC
read_raw_audio_data(void *arg)
{
    pa_sample_spec samp_spec;
    pa_simple *simple = NULL;
    uint32_t bytes_read;
    char *cptr;
    int i;
    int error;
    struct trans *strans;
    char path[256];
    struct stream *outs;

    strans = trans_create(TRANS_MODE_UNIX, 8192, 8192);

    if (strans == 0)
    {
        LOG(0, ("read_raw_audio_data: trans_create failed\n"));
        return 0;
    }

    strans->trans_data_in = sttrans_data_in;
    g_snprintf(path, 255, "/tmp/xrdp_chansrv_audio_socket_%d", g_display_num);

    if (trans_connect(strans, "", path, 100) != 0)
    {
        LOG(0, ("read_raw_audio_data: trans_connect failed\n"));
        trans_delete(strans);
        return 0;
    }

    /* setup audio format */
    samp_spec.format = PA_SAMPLE_S16LE;
    samp_spec.rate = 44100;
    samp_spec.channels = 2;

    /* if we are root, then for first 8 seconds connection to pulseaudo server
       fails; if we are non-root, then connection succeeds on first attempt;
       for now we have changed code to be non-root, but this may change in the
       future - so pretend we are root and try connecting to pulseaudio server
       for upto one minute */
    for (i = 0; i < 60; i++)
    {
        simple = pa_simple_new(NULL, "xrdp", PA_STREAM_RECORD, NULL,
                               "record", &samp_spec, NULL, NULL, &error);

        if (simple)
        {
            /* connected to pulseaudio server */
            LOG(0, ("read_raw_audio_data: connected to pulseaudio server\n"));
            break;
        }

        LOG(0, ("read_raw_audio_data: ERROR creating PulseAudio async interface\n"));
        LOG(0, ("read_raw_audio_data: %s\n", pa_strerror(error)));
        g_sleep(1000);
    }

    if (i == 60)
    {
        /* failed to connect to audio server */
        trans_delete(strans);
        return NULL;
    }

    /* insert header just once */
    outs = trans_get_out_s(strans, 8192);
    out_uint32_le(outs, 0);
    out_uint32_le(outs, AUDIO_BUF_SIZE + 8);
    cptr = outs->p;
    out_uint8s(outs, AUDIO_BUF_SIZE);
    s_mark_end(outs);

    while (1)
    {
        /* read a block of raw audio data... */
        g_memset(cptr, 0, 4);
        bytes_read = pa_simple_read(simple, cptr, AUDIO_BUF_SIZE, &error);

        if (bytes_read < 0)
        {
            LOG(0, ("read_raw_audio_data: ERROR reading from pulseaudio stream\n"));
            LOG(0, ("read_raw_audio_data: %s\n", pa_strerror(error)));
            break;
        }

        /* bug workaround:
           even when there is no audio data, pulseaudio is returning without
           errors but the data itself is zero; we use this zero data to
           determine that there is no audio data present */
        if (*cptr == 0 && *(cptr + 1) == 0 && *(cptr + 2) == 0 && *(cptr + 3) == 0)
        {
            g_sleep(10);
            continue;
        }

        if (trans_force_write_s(strans, outs) != 0)
        {
            LOG(0, ("read_raw_audio_data: ERROR writing audio data to server\n"));
            break;
        }
    }

    pa_simple_free(simple);
    trans_delete(strans);
    return NULL;
}
예제 #27
0
파일: paaudio.c 프로젝트: CPFL/gxen
/* capture */
static void *qpa_thread_in (void *arg)
{
    PAVoiceIn *pa = arg;
    HWVoiceIn *hw = &pa->hw;
    int threshold;

    threshold = conf.divisor ? hw->samples / conf.divisor : 0;

    if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
        return NULL;
    }

    for (;;) {
        int incr, to_grab, wpos;

        for (;;) {
            if (pa->done) {
                goto exit;
            }

            if (pa->dead > threshold) {
                break;
            }

            if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) {
                goto exit;
            }
        }

        incr = to_grab = pa->dead;
        wpos = hw->wpos;

        if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
            return NULL;
        }

        while (to_grab) {
            int error;
            int chunk = audio_MIN (to_grab, hw->samples - wpos);
            void *buf = advance (pa->pcm_buf, wpos);

            if (pa_simple_read (pa->s, buf,
                                chunk << hw->info.shift, &error) < 0) {
                qpa_logerr (error, "pa_simple_read failed\n");
                return NULL;
            }

            hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume);
            wpos = (wpos + chunk) % hw->samples;
            to_grab -= chunk;
        }

        if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
            return NULL;
        }

        pa->wpos = wpos;
        pa->dead -= incr;
        pa->incr += incr;
    }

 exit:
    audio_pt_unlock (&pa->pt, AUDIO_FUNC);
    return NULL;
}
예제 #28
0
파일: source.c 프로젝트: dbuzz/rtlab
static void *
audio_capture_thr(void *args)
{
	int error;
	PSAUDIORECTHRPARAMS params = (PSAUDIORECTHRPARAMS)args;
	pa_simple *pa_context = NULL;
	uint8_t active = 1;
	uint32_t buffer_size;

	SSAMPLEHEADER  sample_header = {0};
	HBUF sample;

	TIMING_MEASURE_AREA;

	buffer_size = HEADER_SIZE + params->sample_spec->channels *
					params->buffer_size * pa_sample_size(params->sample_spec);

	sample_header.number = 0;
	sample_header.buf_type = BUF_TYPE_INTERLEAVED;
	sample_header.sample_size = pa_sample_size(params->sample_spec);
	sample_header.samples = params->buffer_size;
	sample_header.channels = params->sample_spec->channels;
	sample_header.samplerate = params->sample_spec->rate;

	if ( !(pa_context = pa_simple_new(NULL, params->argv[0],
			PA_STREAM_RECORD, NULL, "record",
			params->sample_spec, NULL, NULL, &error)) ) {
		fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
		goto audio_thr_finish;
	}

	printf("[source] audio thr\n");

	while (active) {
		TIMING_START();

		sample = buf_alloc(NULL);
		buf_resize(sample, buffer_size);
		sample->full_size = sample->size = sample->alloced_size;
		sample_zero_buffer(sample);
		memcpy(sample->buf, &sample_header, sizeof(SSAMPLEHEADER));

        if (pa_simple_read(pa_context, sample->buf + HEADER_SIZE,
						sample->alloced_size - HEADER_SIZE, &error) < 0) {
            fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
            goto audio_thr_finish;
        }
		pa_gettimeofday(&(sample_header.timestamp));
		sample_header.number += 1;

		/* printf("[audio] read %p\n", sample); */

		if ( (error = write(params->pipefd, &sample, sizeof(sample))) != sizeof(sample)) {
			if (error == -1) {
				handle_error("[audio] write()");
			}

			buf_free(sample);
			perror("[audio] ");
			printf("[audio] uverrun. free buffer\n");
		}

		active = params->active;

		TIMING_END(" audio");
	}

audio_thr_finish:

	pa_simple_free(pa_context);

	return NULL;
}
예제 #29
0
int main(int argc, char*argv[])
{
	/* The Sample format to use */
	static const pa_sample_spec ss =
	{
		.format = PA_SAMPLE_S16LE,
		.rate = 44100,
		.channels = 2
	};

	pa_simple* dev_out = 0;
	pa_simple* dev_in = 0;

	int ret = 1;
	int error;


	/* Create a new playback stream */
	if (!(dev_out = pa_simple_new(NULL, "Noise Remover", PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error)))
	{
		fprintf(stderr, __FILE__": pa_simple_new() failed: %dev_out\n", pa_strerror(error));
		goto finish;
	}
	if (!(dev_in = pa_simple_new(NULL, "Noise Remover", PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error)))
	{
		fprintf(stderr, __FILE__": pa_simple_new() failed: %dev_out\n", pa_strerror(error));
		goto finish;
	}

	{
		int i;
		float f;

		SpeexPreprocessState* pp = speex_preprocess_state_init(BUFSIZE, ss.rate);

		i = 1;       speex_preprocess_ctl(pp, SPEEX_PREPROCESS_SET_DENOISE, &i);
		i = 1;       speex_preprocess_ctl(pp, SPEEX_PREPROCESS_SET_AGC, &i);
		f = 8000;    speex_preprocess_ctl(pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f);
		i = 1;       speex_preprocess_ctl(pp, SPEEX_PREPROCESS_SET_DEREVERB, &i);
		f = 0.04;     speex_preprocess_ctl(pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
		f = 0.03;     speex_preprocess_ctl(pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);

		double lowest_rms = 99999999999999;
		int silence_count = 0;

		for (;;)
		{
			int16_t buf[BUFSIZE];

			/* Read some data ... */
			if (pa_simple_read(dev_in, buf, sizeof(buf), &error) < 0)
			{
		        fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n",  pa_strerror(error));
		        goto finish;
		    }

		    /* ... Use speex to de-noise ... */
		    double total = 0;
		    for(int n = 0; n < sizeof(buf); n++)
		    	total += buf[n] * buf[n];
		    double rms = std::sqrt(total / sizeof(buf));

		    if(rms < lowest_rms)
		    	lowest_rms = rms;
		    
			
		    if((rms - lowest_rms) < 50) // this value will probably need adjusting for you
		    	silence_count = 0;
			else if(silence_count < 10)
				silence_count++;

			if(silence_count == 10)
				speex_preprocess_run(pp, buf);
			else
				continue; // don't write it out...

			/* ... and play it */
			if (pa_simple_write(dev_out, buf, sizeof(buf), &error) < 0)
			{
				fprintf(stderr, __FILE__": pa_simple_write() failed: %dev_out\n", pa_strerror(error));
				goto finish;
			}
		}
		/* Make sure that every single sample was played */
		if (pa_simple_drain(dev_out, &error) < 0)
		{
			fprintf(stderr, __FILE__": pa_simple_drain() failed: %dev_out\n", pa_strerror(error));
			goto finish;
		}
	}
	ret = 0;
finish:
	if (dev_out)
		pa_simple_free(dev_out);
	if (dev_in)
		pa_simple_free(dev_in);
	return ret;
}
예제 #30
0
// Reads in a message and places it in out limited to the len given
// returns the size of the message
size_t Dialup::read(unsigned char *out, size_t len) {
    // TODO: maybe clean it up a bit more, 
    // it my be losing some bits when it refills the buffer
    int high = 0;
    int low = 0;

    unsigned char hash = 0;

    size_t dataind = 0;
    buffer[dataind] = 0;

    // bypass everthing that isn't the signal
    while (!buffer[buffind]) buffind++;

    while (dataind < len) {
        // grab new data if were done with this block
        if (buffind > buffsize) {
//            printf("!");

            // save the last value for the case of a floating value
            int oldval = buffer[buffsize-2];
            buffind = 0;

            // get the next block of data
            int err = pa_simple_read(audiosrv, buffer, buffsize, 0);
            if (err) throw pa_exception(err);

            // flip the data upside down
            // if its in a middle range assume the previous value
            for (int i=0; i<buffsize; i++) {
                if (buffer[i] < 100) {
                    buffer[i] = 0;
                } else if (buffer[i] > 150) {
                    buffer[i] = 1;
                } else {
                    buffer[i] = i>0 ? buffer[i-1] : oldval;
                }
            }
        }


        // count up highs and lows
        if (buffer[buffind])
            high++;
        else
            low++;

        if (low > 8) { // End of message signal
            if (out[dataind] != hash)
                return -1;
            else
                return dataind;
        }


        if (low+high > 4 && low && buffer[buffind]) {
            if (high > 8) { // End of word signal
//                printf(" |%d|%d[%c]\n", high, low, out[dataind]);

                hash ^= out[dataind];
                out[++dataind] = 0;
            } else { // determine the bit
//                printf("%d", high>low);

                out[dataind] <<= 1;
                out[dataind] |= (high > low);
            }

            high = 0;
            low = 0;
        }

        //skip two as the audio data is interleaved
        buffind += 2;
    }

    return -2;
}