コード例 #1
0
ファイル: SoundPlayer.cpp プロジェクト: ahaug/CamSync
int SoundPlayer::getLatency() {
    if (connection) {
        int error;
        pa_usec_t ret = pa_simple_get_latency(connection, &error);
        return (int)ret;
    } else return 0;
}
コード例 #2
0
bool WaveOutPulseAudio::OpenWaveOutDevice(int pSampleRate, int pOutputChannels)
{
    pa_sample_spec     tOutputFormat;
    int                tRes;
    pa_usec_t          tLatency;

    LOG(LOG_VERBOSE, "Trying to open the wave out device");

    if (mWaveOutOpened)
        return false;

    mSampleRate = pSampleRate;
    mAudioChannels = pOutputChannels;

    LOG(LOG_VERBOSE, "Desired device is %s", mDesiredDevice.c_str());

    if ((mDesiredDevice == "") || (mDesiredDevice == "auto") || (mDesiredDevice == "automatic"))
    {
        LOG(LOG_VERBOSE, "Using default audio device");
        mDesiredDevice = "";
    }

    tOutputFormat.format = PA_SAMPLE_S16LE;
    tOutputFormat.rate = mSampleRate;
    tOutputFormat.channels = mAudioChannels;

    // create a new playback stream
    if (!(mOutputStream = pa_simple_new(NULL, "Homer-Conferencing", PA_STREAM_PLAYBACK, (mDesiredDevice != "" ? mDesiredDevice.c_str() : NULL) /* dev Name */, GetStreamName().c_str(), &tOutputFormat, NULL, NULL, &tRes)))
    {
        LOG(LOG_ERROR, "Couldn't create PulseAudio stream because %s(%d)", pa_strerror(tRes), tRes);
        return false;
    }

    if ((tLatency = pa_simple_get_latency(mOutputStream, &tRes)) == (pa_usec_t) -1)
    {
        LOG(LOG_ERROR, "Couldn't determine the latency of the output stream because %s(%d)", pa_strerror(tRes), tRes);
        pa_simple_free(mOutputStream);
        mOutputStream = NULL;
        return false;
    }

    mCurrentDevice = mDesiredDevice;

    //######################################################
    //### give some verbose output
    //######################################################
    LOG(LOG_INFO, "PortAudio wave out opened...");
    LOG(LOG_INFO,"    ..sample rate: %d", mSampleRate);
    LOG(LOG_INFO,"    ..channels: %d", pOutputChannels);
    LOG(LOG_INFO,"    ..desired device: %s", mDesiredDevice.c_str());
    LOG(LOG_INFO,"    ..selected device: %s", mCurrentDevice.c_str());
    LOG(LOG_INFO,"    ..latency: %"PRIu64" seconds", (uint64_t)tLatency * 1000 * 1000);
    LOG(LOG_INFO,"    ..sample format: %d", PA_SAMPLE_S16LE);

    mWaveOutOpened = true;

    return true;
}
コード例 #3
0
float AudioDriverPulseAudio::get_latency() {

	if (latency == 0) { //only do this once since it's approximate anyway
		int error_code;
		pa_usec_t palat = pa_simple_get_latency(pulse, &error_code);
		latency = double(palat) / 1000000.0;
	}

	return latency;
}
コード例 #4
0
ファイル: oa_pulse.c プロジェクト: Jheengut/gmerlin
static int get_delay_pulse(void * p)
  {
  bg_pa_t * priv;
  int error;
  int ret;
  priv = p;
  ret = gavl_time_rescale(1000000, priv->format.samplerate,
                          pa_simple_get_latency(priv->pa, &error));
  return ret;
  }
コード例 #5
0
ファイル: outputpulseaudio.cpp プロジェクト: Greedysky/qmmp
qint64 OutputPulseAudio::latency()
{
    if (!m_connection)
        return 0;
    int error = 0;
    qint64 delay = pa_simple_get_latency(m_connection, &error)/1000;
    if (error)
    {
        qWarning("OutputPulseAudio: %s", pa_strerror (error));
        delay = 0;
    }
    return delay;
}
コード例 #6
0
ファイル: pa_play_simple.c プロジェクト: gavv/snippets
static void print_info(
    pa_simple* simple,
    pa_sample_spec* sample_spec,
    pa_usec_t start_time,
    uint64_t n_bytes)
{
    const pa_usec_t position = pa_bytes_to_usec(n_bytes, sample_spec);

    const pa_usec_t timestamp = pa_rtclock_now() - start_time;

    const pa_usec_t latency = pa_simple_get_latency(simple, NULL);

    fprintf(stdout, "position=%lu ms, timestamp=%lu ms, diff=%ld ms, latency=%lu ms\n",
            (unsigned long)(position / 1000),
            (unsigned long)(timestamp / 1000),
            (((long)position - (long)timestamp) / 1000),
            (unsigned long)(latency / 1000));
}
コード例 #7
0
ファイル: ao_pulse.c プロジェクト: Distrotech/libao
int ao_plugin_close(ao_device *device) {
    assert(device && device->internal);
    ao_pulse_internal *internal = (ao_pulse_internal *) device->internal;

    if(internal->simple){

      /* this is a PulseAudio ALSA bug workaround;
         pa_simple_drain() always takes about 2 seconds, even if
         there's nothing to drain.  Rather than wait for no
         reason, determine the current playback depth, wait
         that long, then kill the stream.  Remove this code
         once Pulse gets fixed. */

      pa_usec_t us = pa_simple_get_latency(internal->simple, NULL);
      if(us<0 || us>1000000){
        pa_simple_drain(internal->simple, NULL);
      }else{
        us -= internal->static_delay;
        if(us>0){
          struct timespec sleep,wake;
          sleep.tv_sec = (int)(us/1000000);
          sleep.tv_nsec = (us-sleep.tv_sec*1000000)*1000;
          while(nanosleep(&sleep,&wake)<0){
            if(errno==EINTR)
              sleep=wake;
            else
              break;
          }
        }
      }

      pa_simple_free(internal->simple);
      internal->simple = NULL;
    }

    return 1;
}
コード例 #8
0
ファイル: ao_pulse.c プロジェクト: Distrotech/libao
int ao_plugin_open(ao_device *device, ao_sample_format *format) {
    char *p=NULL, t[256], t2[256];
    const char *fn = NULL;
    ao_pulse_internal *internal;
    struct pa_sample_spec ss;
    struct pa_channel_map map;
    struct pa_buffer_attr battr;
    size_t allocated = 128;

    assert(device && device->internal && format);

    internal = (ao_pulse_internal *) device->internal;

    if (format->bits == 8)
      ss.format = PA_SAMPLE_U8;
    else if (format->bits == 16)
      ss.format = PA_SAMPLE_S16NE;
#ifdef PA_SAMPLE_S24NE
    else if (format->bits == 24)
      ss.format = PA_SAMPLE_S24NE;
#endif
    else
        return 0;

    if (device->output_channels <= 0 || device->output_channels > PA_CHANNELS_MAX)
      return 0;

    ss.channels = device->output_channels;
    ss.rate = format->rate;

    disable_sigpipe();

    if (internal->client_name) {
        snprintf(t, sizeof(t), "libao[%s]", internal->client_name);
        snprintf(t2, sizeof(t2), "libao[%s] playback stream", internal->client_name);
    } else {
      while (1) {
        p = pa_xmalloc(allocated);

        if (!(fn = pa_get_binary_name(p, allocated))) {
          break;
        }

        if (fn != p || strlen(p) < allocated - 1) {
          fn = pa_path_get_filename(fn);
          snprintf(t, sizeof(t), "libao[%s]", fn);
          snprintf(t2, sizeof(t2), "libao[%s] playback stream", fn);
          break;
        }

        pa_xfree(p);
        allocated *= 2;
      }
      pa_xfree(p);
      p = NULL;
      if (!fn) {
        strcpy(t, "libao");
        strcpy(t2, "libao playback stream");
      }
    }

    if(device->input_map){
      int i;
      pa_channel_map_init(&map);
      map.channels=device->output_channels;

      for(i=0;i<device->output_channels;i++){
        if(device->input_map[i]==-1){
          map.map[i] = PA_CHANNEL_POSITION_INVALID;
        }else{
          map.map[i] = device->input_map[i];
        }
      }
    }

    /* buffering attributes */
    battr.prebuf = battr.minreq = battr.fragsize = -1;

    battr.tlength = (int)(internal->buffer_time * format->rate) / 1000000 *
      ((format->bits+7)/8) + device->output_channels;
    battr.minreq = battr.tlength/4;
    battr.maxlength = battr.tlength+battr.minreq;

    internal->simple = pa_simple_new(internal->server, t, PA_STREAM_PLAYBACK,
                                     internal->sink, t2, &ss,
                                     (device->input_map ? &map : NULL), &battr, NULL);
    if (!internal->simple)
        return 0;

    device->driver_byte_format = AO_FMT_NATIVE;

    internal->static_delay = pa_simple_get_latency(internal->simple, NULL);
    if(internal->static_delay<0) internal->static_delay = 0;

    return 1;
}
コード例 #9
0
ファイル: AudDrv_Pulse.c プロジェクト: ValleyBell/libvgm
UINT32 Pulse_GetLatency(void* drvObj)
{
	DRV_PULSE* drv = (DRV_PULSE*)drvObj;
	
	return (UINT32)(pa_simple_get_latency(drv->hPulse, NULL) / 1000);
}
コード例 #10
0
/**
    \fn    localInit
    \brief Take & initialize the device

*/
bool pulseSimpleAudioDevice::localInit(void) 
{
ADM_info("Pulse, initiliazing channel=%d samplerate=%d\n",(int)_channels,(int)_frequency);
pa_simple *s;
pa_sample_spec ss;
int er;
pa_buffer_attr attr;
pa_channel_map map,*pmap=NULL;
    attr.maxlength = (uint32_t) -1;
    attr.tlength = (uint32_t )-1;
    attr.prebuf =(uint32_t) -1;
    attr.minreq = (uint32_t) -1;
    attr.fragsize =(uint32_t) -1;

  // We want something like 20 ms latency
   uint64_t bufSize=_frequency;
            bufSize*=_channels;
            bufSize*=2;      // 1 second worth of audio

  bufSize=bufSize/1000;
  bufSize*=ADM_PULSE_LATENCY;
  attr.tlength=bufSize;       // Latency in bytes
 

  // Channel mapping
  if(_channels>2)
    {
        pmap=&map;
        map.channels=_channels;
        map.map[0]=PA_CHANNEL_POSITION_FRONT_LEFT;
        map.map[1]=PA_CHANNEL_POSITION_FRONT_RIGHT;
        map.map[2]=PA_CHANNEL_POSITION_FRONT_CENTER;
        map.map[3]=PA_CHANNEL_POSITION_REAR_LEFT;
        map.map[4]=PA_CHANNEL_POSITION_REAR_RIGHT;
        map.map[5]=PA_CHANNEL_POSITION_SUBWOOFER;
  }

  ss.format = PA_SAMPLE_S16LE;
  ss.channels = _channels;
  ss.rate =_frequency;
 
  instance= pa_simple_new(NULL,               // Use the default server.
                    "Avidemux2",           // Our application's name.
                    PA_STREAM_PLAYBACK,
                    NULL,               // Use the default device.
                    "Sound",            // Description of our stream.
                    &ss,                // Our sample format.
                    pmap,               // Use default channel map
                    &attr ,             // Use default buffering attributes.
                    &er               // Ignore error code.
                    );
  if(!instance)
    {
        ADM_info("[PulseSimple] open failed :%s\n",pa_strerror(er));
        return 0;
    }
#if 0
    pa_usec_t l=0;
    // Latency...
    Clock    ticktock;
    ticktock.reset();
    if(0>pa_simple_write(INSTANCE,silence, sizeOf10ms,&er))
    {
      fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(er));
    }
    pa_simple_drain(INSTANCE,&er);
    latency=ticktock.getElapsedMS();
    ADM_info("[Pulse] Latency :%"PRIu32", total %"PRIu32"\n",latency,pa_simple_get_latency(INSTANCE,&er)/1000);
#endif
    ADM_info("[PulseSimple] open ok for fq=%d channels=%d\n",ss.rate,ss.channels);
    return 1;

}
コード例 #11
0
ファイル: pa_fft.c プロジェクト: atomnuker/pa_fft
void *pa_fft_thread(void *arg) {
    struct pa_fft *t = (struct pa_fft *)arg;
    float weights[t->buffer_samples];

    graph_init(t);
    avg_buf_init(t);
    weights_init(weights, t->fft_memb, t->win_type);

    while (t->cont) {
        while(SDL_PollEvent(&t->event)) {
            switch(t->event.type) {
                case SDL_QUIT:
                    t->cont = 0;
                    break;
                case SDL_WINDOWEVENT:
                    SDL_GL_GetDrawableSize(t->win, &t->width, &t->height);
                    glViewport(0, 0, t->width, t->height);
                    break;
                default:
                    break;
            }
        }

        if (t->overlap)
            memcpy(&t->pa_buf[0], &t->pa_buf[t->pa_samples],
                   t->pa_samples*sizeof(float));

        pa_usec_t lag = pa_simple_get_latency(t->s, &t->error);

        if (pa_simple_read(t->s, &t->pa_buf[t->overlap ? t->pa_samples : 0],
            t->pa_buf_size, &t->error) < 0) {
            fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n",
                    pa_strerror(t->error));
            t->cont = 0;
            continue;
        }

        apply_win(t->buffer, t->pa_buf, weights, t->buffer_samples);
        fftw_execute(t->plan);

        double freq_low, freq_disp, freq_range, freq_off, mag_max = 0.0f;
        if (t->log_graph) {
            freq_low = log10((t->start_low*t->fft_fund_freq)/((float)t->ss.rate/2));
            freq_disp = 1.0 - log10((t->fft_memb*t->fft_fund_freq)/((float)t->ss.rate/2));
            freq_range = (1.0 - freq_disp) - freq_low;
            freq_off = 0.0f;
        } else {
            freq_low = (t->start_low*t->fft_fund_freq)/((float)t->ss.rate/2);
            freq_disp = 1.0 - (t->fft_memb*t->fft_fund_freq)/((float)t->ss.rate/2);
            freq_range = (1.0 - freq_disp) - freq_low;
            freq_off = 1.0f;
        }
        for (int i = t->start_low; i < t->fft_memb; i++) {
            fftw_complex num = t->output[i];
            double mag = creal(num)*creal(num) + cimag(num)*cimag(num);
            mag = log10(mag)/10;
            mag = frame_average(mag, t->frame_avg_mag[i], t->frame_avg, 1);
            mag_max = mag > mag_max ? mag : mag_max;
        }

        if (!t->no_refresh)
            glClear(GL_COLOR_BUFFER_BIT);
        glBegin(GL_LINE_STRIP);
        if ((float)lag/1000000 < 1.0f)
            glColor3f(255.0,255.0,255.0);
        else
            glColor3f(255.0,0.0,0.0);
        for (int i = t->start_low; i < t->fft_memb; i++) {
            double freq;
            fftw_complex num = t->output[i];
            if (t->log_graph)
                freq = log10((i*t->fft_fund_freq)/((float)t->ss.rate/2));
            else
                freq = (i*t->fft_fund_freq)/((float)t->ss.rate/2);
            double mag = creal(num)*creal(num) + cimag(num)*cimag(num);
            mag = log10(mag)/10;
            mag = frame_average(mag, t->frame_avg_mag[i], t->frame_avg, 0);
            glVertex2f((freq/freq_range + freq_disp/2)*2 - freq_off, mag + mag_max + 0.5f);
        }
        glEnd();

        SDL_GL_SwapWindow(t->win);
    }

    SDL_DestroyWindow(t->win);
    SDL_Quit();

    deinit_fft(t);

    return NULL;
}