Esempio n. 1
0
File: alsa.c Progetto: 9heart/DT3
static ALCuint alsa_available_samples(ALCdevice *Device)
{
    alsa_data *data = (alsa_data*)Device->ExtraData;
    snd_pcm_sframes_t avail;

    avail = (Device->Connected ? snd_pcm_avail_update(data->pcmHandle) : 0);
    if(avail < 0)
    {
        ERR("avail update failed: %s\n", snd_strerror(avail));

        if((avail=snd_pcm_recover(data->pcmHandle, avail, 1)) >= 0)
        {
            if(data->doCapture)
                avail = snd_pcm_start(data->pcmHandle);
            if(avail >= 0)
                avail = snd_pcm_avail_update(data->pcmHandle);
        }
        if(avail < 0)
        {
            ERR("restore error: %s\n", snd_strerror(avail));
            aluHandleDisconnect(Device);
        }
    }
    while(avail > 0)
    {
        snd_pcm_sframes_t amt;

        amt = snd_pcm_bytes_to_frames(data->pcmHandle, data->size);
        if(avail < amt) amt = avail;

        amt = snd_pcm_readi(data->pcmHandle, data->buffer, amt);
        if(amt < 0)
        {
            ERR("read error: %s\n", snd_strerror(amt));

            if(amt == -EAGAIN)
                continue;
            if((amt=snd_pcm_recover(data->pcmHandle, amt, 1)) >= 0)
            {
                if(data->doCapture)
                    amt = snd_pcm_start(data->pcmHandle);
                if(amt >= 0)
                    amt = snd_pcm_avail_update(data->pcmHandle);
            }
            if(amt < 0)
            {
                ERR("restore error: %s\n", snd_strerror(amt));
                aluHandleDisconnect(Device);
                break;
            }
            avail = amt;
            continue;
        }

        WriteRingBuffer(data->ring, data->buffer, amt);
        avail -= amt;
    }

    return RingBufferSize(data->ring);
}
static int drvHostALSAAudioGetAvail(snd_pcm_t *phPCM, snd_pcm_sframes_t *pFramesAvail)
{
    AssertPtrReturn(phPCM, VERR_INVALID_POINTER);
    AssertPtrReturn(pFramesAvail, VERR_INVALID_POINTER);

    int rc;

    snd_pcm_sframes_t framesAvail;
    framesAvail = snd_pcm_avail_update(phPCM);
    if (framesAvail < 0)
    {
        if (framesAvail == -EPIPE)
        {
            rc = drvHostALSAAudioRecover(phPCM);
            if (RT_SUCCESS(rc))
                framesAvail = snd_pcm_avail_update(phPCM);
        }
        else
            rc = VERR_ACCESS_DENIED; /** @todo Find a better rc. */
    }
    else
        rc = VINF_SUCCESS;

    if (framesAvail >= 0)
        *pFramesAvail = framesAvail;

    return rc;
}
Esempio n. 3
0
int QAudioOutputPrivate::bytesFree() const
{
    if(resuming)
        return period_size;

    if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
        return 0;

    int frames = snd_pcm_avail_update(handle);
    if (frames == -EPIPE) {
        // Try and handle buffer underrun
        int err = snd_pcm_recover(handle, frames, 0);
        if (err < 0)
            return 0;
        else
            frames = snd_pcm_avail_update(handle);
    } else if (frames < 0) {
        return 0;
    }

    if ((int)frames > (int)buffer_frames)
        frames = buffer_frames;

    return snd_pcm_frames_to_bytes(handle, frames);
}
Esempio n. 4
0
    void write( const char *data, qint64 len )
    {
        if ( !handle )
            return;

        int count=0;

        qLog(QAudioOutput)<<"frames to write out = "<<
            snd_pcm_bytes_to_frames( handle, (int)len )<<" ("<<len<<") bytes";

        while ( len > 0 ) {

            int err=0;
            int frames = snd_pcm_bytes_to_frames( handle, (int)len );

#ifdef ALSA_USE_AVAILABLE
            if(frames < (int)period_size)
                return;

            int available = snd_pcm_avail_update(handle);
            qLog(QAudioOutput) <<"available space = "<<available;
            if(available == 0) {
                while(available < frames) {
                    snd_pcm_wait(handle,period_size/1000);
                    usleep(period_size*10);
                    available = snd_pcm_avail_update(handle);
                    qLog(QAudioOutput) <<"->available space = "<<available;
                    count++;
                    if((count > 5)||(available < 0))
                        return;
                }
            }
#endif

            err = snd_pcm_writei( handle, data, frames );

            // Handle errors
            if ( err >= 0 ) {
                if(err == 0) count++;
                int bytes = snd_pcm_frames_to_bytes( handle, err );
                qLog(QAudioOutput) << QString("write out = %1").arg(bytes).toLatin1().constData();
                data += bytes;
                len -= bytes;
            } else {
                count++;
                qLog(QAudioOutput) <<"err = "<<err;
                err = xrun_recovery(err);
            }
            if(count > 5) {
                qLog(QAudioOutput) <<"failing to write, close() and re-open() to try and recover!";
                close();
                open();
                snd_pcm_prepare(handle);
                break;
            }
        }
    }
Esempio n. 5
0
void *speaker_thread(void* ptr){
  audiobuffer* buf = ((spk_pcm_package*)ptr)->buffer; //cast pointer, get buffer struct
  snd_pcm_t* speaker_handle = ((spk_pcm_package*)ptr)->pcm_handle; //cast pointer, get device pointer
  free(ptr); //free message memory
    
  snd_pcm_nonblock(speaker_handle, SND_PCM_NONBLOCK); //set in nonblocking mode
    
  char started = 0;  //track when to start reading data
  while(!global_kill && !speaker_kill_flag) { //loop until program stops us
    //wait until adequate buffer is achieved and can be written
    if((!started && BUFFER_SIZE(*buf) < (MIN_BUFFER)) \
        || BUFFER_EMPTY(*buf) \
        || !snd_pcm_avail_update(speaker_handle)) {
      //printf("Speaker Waiting\n");
      usleep(PERIOD_UTIME*2); //wait to reduce CPU usage
      continue;     //don't start yet
    } else {
      if(!started) snd_pcm_prepare(speaker_handle); //reset speaker
      started = 1; //indicate that we've startd
    }
    
    //write data to speaker buffer, check responses
    int write_count = MIN(BUFFER_SIZE(*buf), snd_pcm_avail_update(speaker_handle)/(buf->period));
    
#ifdef DEBUG_MODE
    printf("Writing %d packets to speaker\n", write_count);
#endif

    //loop over avaliable buffer entries
    while(write_count-- > 0 && started){
      /* Note: This call performs a syscall to copy data to kernel space 
          so it would be better to write multiple entries in one operation, 
          but using the audiobuffer without the abstraction was something 
          I didn't want to do at the time of writing. */
      int rc = snd_pcm_writei(speaker_handle, GET_QUEUE_HEAD(*buf), buf->period);      
      INC_QUEUE_HEAD(*buf);
      if (rc == -EPIPE){ //Catch underruns (not enough data)
        fprintf(stderr, "underrun occurred\n");
        started = 0;  //stop and wait for buffer to buildup
      } else if (rc < 0) fprintf(stderr, "error from writei: %s\n", snd_strerror(rc)); //other errors
      else if (rc != (int)buf->period) fprintf(stderr, "short write, write %d frames\n", rc);
      //else fprintf(stderr, "audio written correctly\n");
      //snd_pcm_wait(speaker_handle, 1000); //wait for IO to be ready
    }
    
#ifdef DEBUG_MODE
    printf("%d unwritten\n", write_count);
#endif    
  }
  
  // notify kernel to empty/close the speakers
  snd_pcm_drain(speaker_handle);  //finish transferring the audio
  snd_pcm_close(speaker_handle);  //close the device
  printf("Audio Controller: Speaker Thread shutdown\n");
  
  pthread_exit(NULL); //exit thread safetly
}
Esempio n. 6
0
/**************************************************************************
 * 			     wodPlayer_FeedDSP			[internal]
 * Feed as much sound data as we can into the DSP and return the number of
 * milliseconds before it will be necessary to feed the DSP again.
 */
static DWORD wodPlayer_FeedDSP(WINE_WAVEDEV* wwo)
{
    DWORD               availInQ;

    wodUpdatePlayedTotal(wwo, NULL);
    availInQ = snd_pcm_avail_update(wwo->pcm);

    /* no more room... no need to try to feed */
    if (availInQ > 0) {
        /* Feed from partial wavehdr */
        if (wwo->lpPlayPtr && wwo->dwPartialOffset != 0) {
            wodPlayer_WriteMaxFrags(wwo, &availInQ);
        }

        /* Feed wavehdrs until we run out of wavehdrs or DSP space */
        if (wwo->dwPartialOffset == 0 && wwo->lpPlayPtr) {
            do {
                TRACE("Setting time to elapse for %p to %u\n",
                      wwo->lpPlayPtr, wwo->dwWrittenTotal + wwo->lpPlayPtr->dwBufferLength);
                /* note the value that dwPlayedTotal will return when this wave finishes playing */
                wwo->lpPlayPtr->reserved = wwo->dwWrittenTotal + wwo->lpPlayPtr->dwBufferLength;
            } while (wodPlayer_WriteMaxFrags(wwo, &availInQ) && wwo->lpPlayPtr && availInQ > 0);
        }
    }

    return wodPlayer_DSPWait(wwo);
}
Esempio n. 7
0
/* from PA */
static snd_pcm_sframes_t alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const StreamSpec& ss)
{
    snd_pcm_sframes_t n;
    size_t k;

    /* Some ALSA drivers expose weird bugs, let's inform the user about what is going on */

    n = snd_pcm_avail_update(pcm);

    if (n <= 0)
        return n;

    k = (size_t) n * ss.FrameBytes();

    if (k >= hwbuf_size * 5 ||
        k >= ss.BytesPerSecond() * 10)
    {
        // Print this on console to allow users to report their driver.
        printf("snd_pcm_avail_update() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
               "Most likely this is a bug in the ALSA driver. Please report this issue to the ALSA developers.\n",
               (unsigned long) k,
               (unsigned long) ss.FramesToMs(k / ss.FrameBytes()));

        /* Mhmm, let's try not to fail completely */
        n = (snd_pcm_sframes_t) (hwbuf_size / ss.FrameBytes());
    }

    return n;
}
Esempio n. 8
0
static int alsa_can_read(snd_pcm_t *dev)
{
	snd_pcm_sframes_t avail;
	int err;

	alsa_resume(dev);
	avail = snd_pcm_avail_update(dev);
	/* A buggy driver does not return an error while being in Xrun */
	if (avail >= 0 && snd_pcm_state(dev) == SND_PCM_STATE_XRUN) avail=-EPIPE;
	if (avail < 0) {
		ms_error("snd_pcm_avail_update: %s", snd_strerror(avail));	// most probably -EPIPE
		/* overrun occured, snd_pcm_state() would return SND_PCM_STATE_XRUN
		 FIXME: handle other error conditions*/
		ms_error("*** alsa_can_read fixup, trying to recover");
		snd_pcm_drain(dev); /* Ignore possible error, at least -EAGAIN.*/
		err = snd_pcm_recover(dev, avail, 0);
		if (err){
			ms_error("snd_pcm_recover() failed with err %d: %s", err, snd_strerror(err));
			return -1;
		}
		err = snd_pcm_start(dev);
		if (err){
			ms_error("snd_pcm_start() failed with err %d: %s", err, snd_strerror(err));
			return -1;
		}
		ms_message("Recovery done");
	}
	return avail;
}
Esempio n. 9
0
static bool_t alsa_can_read(snd_pcm_t *dev, int frames)
{
	snd_pcm_sframes_t avail;
	int err;

	avail = snd_pcm_avail_update(dev);
	ms_debug("*** %s %d %d", __FUNCTION__, (long)avail, frames);
	if (avail < 0) {
		ms_error("snd_pcm_avail_update: %s\n", snd_strerror(avail));	// most probably -EPIPE
		/* overrun occured, snd_pcm_state() would return SND_PCM_STATE_XRUN
		 FIXME: handle other error conditions*/
		ms_error("*** alsa_can_read fixup, trying to recover");
		snd_pcm_drain(dev); /* Ignore possible error, at least -EAGAIN.*/
		err = snd_pcm_recover(dev, avail, 0);
		if (err){ 
			ms_error("snd_pcm_recover() failed with err %d: %s", err, snd_strerror(err));
			return FALSE;
		}
		err = snd_pcm_start(dev);
		if (err){ 
			ms_error("snd_pcm_start() failed with err %d: %s\n", err, snd_strerror(err)); 
			return FALSE; 
		}
		ms_message("Recovery done\n");
	}
	return avail >= frames;
}
Esempio n. 10
0
static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface)
{
    const snd_pcm_channel_area_t *areas;
    snd_pcm_uframes_t avail;
    snd_pcm_format_t format;
    IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
    TRACE("(%p)\n",iface);

    /* **** */
    EnterCriticalSection(&This->pcm_crst);
    avail = This->mmap_buflen_frames;
    snd_pcm_drop(This->pcm);
    snd_pcm_prepare(This->pcm);
    avail = snd_pcm_avail_update(This->pcm);
    snd_pcm_hw_params_get_format(This->hw_params, &format);
    if (This->mmap)
    {
        snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &avail);
        snd_pcm_format_set_silence(format, areas->addr, This->mmap_buflen_frames);
        snd_pcm_mmap_commit(This->pcm, This->mmap_pos, 0);
    }
    else
    {
        snd_pcm_format_set_silence(format, This->mmap_buffer, This->mmap_buflen_frames);
        snd_pcm_writei(This->pcm, This->mmap_buffer, This->mmap_buflen_frames);
        This->mmap_pos = 0;
    }

    /* **** */
    LeaveCriticalSection(&This->pcm_crst);
    return DS_OK;
}
Esempio n. 11
0
/** Fill buffers, for starting and stopping
 * Alsa won't start playing until everything is filled up
 * This also updates mmap_pos
 *
 * Returns: Amount of periods in use so snd_pcm_avail_update
 * doesn't have to be called up to 4x in GetPosition()
 */
static snd_pcm_uframes_t CommitAll(IDsDriverBufferImpl *This)
{
    const snd_pcm_channel_area_t *areas;
    snd_pcm_uframes_t used;
    const snd_pcm_uframes_t commitahead = This->mmap_commitahead;

    used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm);
    TRACE("%p needs to commit to %lu, used: %lu\n", This, commitahead, used);
    if (used < commitahead)
    {
        snd_pcm_uframes_t done, putin = commitahead - used;
        snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
        done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
        This->mmap_pos += done;
        used += done;
        putin = commitahead - used;

        if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0)
        {
            snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
            done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
            This->mmap_pos += done;
            used += done;
        }
    }

    if (This->mmap_pos == This->mmap_buflen_frames)
        This->mmap_pos = 0;

    return used;
}
Esempio n. 12
0
/**************************************************************************
 * 				wodUpdatePlayedTotal	[internal]
 *
 */
static BOOL wodUpdatePlayedTotal(WINE_WAVEDEV* wwo, snd_pcm_status_t* ps)
{
    snd_pcm_sframes_t delay;
    snd_pcm_sframes_t avail;
    snd_pcm_uframes_t buf_size = 0;
    snd_pcm_state_t state;

    state = snd_pcm_state(wwo->pcm);
    avail = snd_pcm_avail_update(wwo->pcm);
    snd_pcm_hw_params_get_buffer_size(wwo->hw_params, &buf_size);
    delay = buf_size - avail;

    if (state != SND_PCM_STATE_RUNNING && state != SND_PCM_STATE_PREPARED)
    {
        WARN("Unexpected state (%d) while updating Total Played, resetting\n", state);
        wine_snd_pcm_recover(wwo->pcm, -EPIPE, 0);
        delay=0;
    }

    /* A delay < 0 indicates an underrun; for our purposes that's 0.  */
    if (delay < 0)
    {
        WARN("Unexpected delay (%ld) while updating Total Played, resetting\n", delay);
        delay=0;
    }

    InterlockedExchange((LONG*)&wwo->dwPlayedTotal, wwo->dwWrittenTotal - snd_pcm_frames_to_bytes(wwo->pcm, delay));
    return TRUE;
}
Esempio n. 13
0
    // Invoked by the static ExternalCallback method below.
    void _InternalCallback()
    {
        snd_pcm_sframes_t avail;
        fprintf(stderr, "* SPU2-X:Iz in your internal callback.\n");

        avail = snd_pcm_avail_update(handle);
        while (avail >= (int)period_time) {
            StereoOut16 buff[PacketsPerBuffer * SndOutPacketSize];
            StereoOut16 *p1 = buff;

            for (int p = 0; p < PacketsPerBuffer; p++, p1 += SndOutPacketSize)
                SndBuffer::ReadSamples(p1);

            snd_pcm_writei(handle, buff, period_time);
            avail = snd_pcm_avail_update(handle);
        }
    }
Esempio n. 14
0
void play_audio(float* xmbuffer, float* alsabuffer) {
	snd_pcm_sframes_t avail;

	while((avail = snd_pcm_avail_update(device)) >= period_size) {
		xm_generate_samples(xmctx, xmbuffer, period_size >> 1);
		play_floatbuffer(device, format, period_size, 1.f, xmbuffer, alsabuffer);
	}
}
Esempio n. 15
0
eU32 tfAlsa::getPlayBufferlen()
{
	if (m_handle == NULL)
		return 0;

	eU32 len = snd_pcm_avail_update(m_handle);
	//printf("%i\n", len);
	return len;
}
Esempio n. 16
0
int AudioInputALSA::PcmRead(void* buf, uint nbytes)
{
    unsigned char* bufptr = (unsigned char*)buf;
    snd_pcm_uframes_t to_read = snd_pcm_bytes_to_frames(pcm_handle, nbytes);
    snd_pcm_uframes_t nframes = to_read;
    snd_pcm_sframes_t nread, avail;
    int retries = 0;
    while (nframes > 0 && retries < 3)
    {
        if (AlsaBad((avail = snd_pcm_avail_update(pcm_handle)),
                    "available update failed"))
        {
            if (!Recovery(avail))
            {
                ++retries;
                continue;
            }
        }
        if ((nread = snd_pcm_readi(pcm_handle, bufptr, nframes)) < 0)
        {
            switch (nread)
            {
            case -EAGAIN:
                break;
            case -EBADFD:
                LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
                    QString("in a state unfit to read (%1): %2")
                    .arg(nread).arg(snd_strerror(nread)));
                break;
            case -EINTR:
            case -EPIPE:
            case -ESTRPIPE:
                Recovery(nread);
                break;
            default:
                LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
                    QString("weird return from snd_pcm_readi: %1")
                    .arg(snd_strerror(nread)));
                break;
            }
        }
        else
        {
            nframes -= nread;
            bufptr += snd_pcm_frames_to_bytes(pcm_handle, nread);
        }
        ++retries;
    }
    if (nframes > 0)
        LOG(VB_AUDIO, LOG_ERR, LOC_DEV +
            QString("short pcm read, %1 of %2 frames, retries %3")
            .arg(to_read - nframes).arg(to_read).arg(retries));
    return snd_pcm_frames_to_bytes(pcm_handle, to_read - nframes);
}
Esempio n. 17
0
/** Fill buffers, for starting and stopping
 * Alsa won't start playing until everything is filled up
 * This also updates mmap_pos
 *
 * Returns: Amount of periods in use so snd_pcm_avail_update
 * doesn't have to be called up to 4x in GetPosition()
 */
static snd_pcm_uframes_t CommitAll(IDsDriverBufferImpl *This)
{
    const snd_pcm_channel_area_t *areas;
    snd_pcm_sframes_t used;
    const snd_pcm_uframes_t commitahead = This->mmap_commitahead;

    used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm);
    if (used < 0) used = 0;
    TRACE("%p needs to commit to %lu, used: %ld\n", This, commitahead, used);
    if (used < commitahead)
    {
        snd_pcm_sframes_t done;
        snd_pcm_uframes_t putin = commitahead - used;
        if (This->mmap)
        {
            snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
            done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
        }
        else
        {
            if (putin + This->mmap_pos > This->mmap_buflen_frames)
                putin = This->mmap_buflen_frames - This->mmap_pos;
            done = snd_pcm_writei(This->pcm, This->mmap_buffer + snd_pcm_frames_to_bytes(This->pcm, This->mmap_pos), putin);
            if (done < putin) WARN("Short write %ld/%ld\n", putin, done);
        }
        if (done < 0) done = 0;
        This->mmap_pos += done;
        used += done;
        putin = commitahead - used;

        if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0)
        {
            if (This->mmap)
            {
                snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
                done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
                This->mmap_pos += done;
            }
            else
            {
                done = snd_pcm_writei(This->pcm, This->mmap_buffer, putin);
                if (done < putin) WARN("Short write %ld/%ld\n", putin, done);
                if (done < 0) done = 0;
                This->mmap_pos = done;
            }
            used += done;
        }
    }

    if (This->mmap_pos == This->mmap_buflen_frames)
        This->mmap_pos = 0;

    return used;
}
Esempio n. 18
0
static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
        LPDWORD lpdwPlay, LPDWORD lpdwWrite)
{
    IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
    snd_pcm_uframes_t hw_pptr, hw_wptr;
    snd_pcm_state_t state;

    /* **** */
    EnterCriticalSection(&This->pcm_crst);

    if (!This->pcm)
    {
        FIXME("Bad pointer for pcm: %p\n", This->pcm);
        LeaveCriticalSection(&This->pcm_crst);
        return DSERR_GENERIC;
    }

    if (!lpdwPlay && !lpdwWrite)
        CommitAll(This);

    state = snd_pcm_state(This->pcm);

    if (state != SND_PCM_STATE_PREPARED && state != SND_PCM_STATE_RUNNING)
    {
        CheckXRUN(This);
        state = snd_pcm_state(This->pcm);
    }
    if (state == SND_PCM_STATE_RUNNING)
    {
        snd_pcm_uframes_t used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm);

        if (This->mmap_pos > used)
            hw_pptr = This->mmap_pos - used;
        else
            hw_pptr = This->mmap_buflen_frames + This->mmap_pos - used;
        hw_pptr %= This->mmap_buflen_frames;

        TRACE("At position: %ld (%ld) - Used %ld\n", hw_pptr, This->mmap_pos, used);
    }
    else hw_pptr = This->mmap_pos;
    hw_wptr = This->mmap_pos;

    LeaveCriticalSection(&This->pcm_crst);
    /* **** */

    if (lpdwPlay)
        *lpdwPlay = snd_pcm_frames_to_bytes(This->pcm, hw_pptr);
    if (lpdwWrite)
        *lpdwWrite = snd_pcm_frames_to_bytes(This->pcm, hw_wptr);

    TRACE("hw_pptr=0x%08x, hw_wptr=0x%08x playpos=%d, writepos=%d\n", (unsigned int)hw_pptr, (unsigned int)hw_wptr, lpdwPlay?*lpdwPlay:-1, lpdwWrite?*lpdwWrite:-1);
    return DS_OK;
}
Esempio n. 19
0
unsigned int
sound_get_buffer ()
{
  int ret;
  snd_pcm_uframes_t buffer_size, period_size;

  ret = snd_pcm_get_params (handle, &buffer_size, &period_size);
  if (ret < 0)
    return 0;

  return buffer_size - snd_pcm_avail_update (handle);
}
Esempio n. 20
0
static int
alsa_audio_deliver(audio_decoder_t *ad, int samples, int64_t pts, int epoch)
{
  decoder_t *d = (decoder_t *)ad;
  media_pipe_t *mp = ad->ad_mp;
  int c;

 retry:
  c = snd_pcm_wait(d->h, 100);
  if(c >= 0) {
    c = snd_pcm_avail_update(d->h);
  }
  if(c == -EPIPE) {
    snd_pcm_prepare(d->h);
    usleep(100000);
    TRACE(TRACE_DEBUG, "ALSA", "Audio underrun");
    d->samples = 0;
    goto retry;
  }

  c = MIN(d->max_frames_per_write, c);

  uint8_t *planes[8] = {0};
  planes[0] = d->tmp;
  c = avresample_read(ad->ad_avr, planes, c);
  
  snd_pcm_status_t *status;
  int err;
  snd_pcm_status_alloca(&status);
  if ((err = snd_pcm_status(d->h, status)) >= 0) {

    if(pts != AV_NOPTS_VALUE) {
      snd_htimestamp_t hts;
      snd_pcm_status_get_trigger_htstamp(status, &hts);
      int64_t ts = hts.tv_sec * 1000000LL + hts.tv_nsec / 1000;
      ts += d->samples * 1000000LL / ad->ad_out_sample_rate;

      hts_mutex_lock(&mp->mp_clock_mutex);
      mp->mp_audio_clock_avtime = ts;
      mp->mp_audio_clock = pts;
      mp->mp_audio_clock_epoch = epoch;
      hts_mutex_unlock(&mp->mp_clock_mutex);
    }
  }

  snd_pcm_sframes_t fr;
  if(!snd_pcm_delay(d->h, &fr))
    ad->ad_delay = 1000000L * fr / ad->ad_out_sample_rate;

  c = snd_pcm_writei(d->h, d->tmp, c);
  d->samples += c;
  return 0;
}
Esempio n. 21
0
    int GetEmptySampleCount()
    {
        if (handle == NULL) {
            fprintf(stderr, "Handle is NULL!\n");
            return 0;
        }

        // Returns the amount of free buffer space, in samples.
        int l = snd_pcm_avail_update(handle);
        if (l < 0)
            return 0;
        return (l / 1000) * (SampleRate / 1000);
    }
Esempio n. 22
0
static int alsa_bufferspace(void)
{
#ifdef HAVE_SND_PCM_AVAIL
    snd_pcm_sframes_t space = snd_pcm_avail(handle);
#else
    snd_pcm_sframes_t space = snd_pcm_avail_update(handle);
#endif
    /* keep alsa values real. Values < 0 mean errors, call to alsa_write
     * will resume. */
    if (space < 0 || space > alsa_bufsize)
        space = alsa_bufsize;
    return space;
}
int QAudioOutputPrivate::bytesFree() const
{
    if(resuming)
        return period_size;

    if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
        return 0;
    int frames = snd_pcm_avail_update(handle);
    if((int)frames > (int)buffer_frames)
        frames = buffer_frames;

    return snd_pcm_frames_to_bytes(handle, frames);
}
Esempio n. 24
0
int
sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes) {
  snd_pcm_sframes_t frames, nframes, avail;

  if (s == NULL || s->output_unit == NULL) {
    return SA_ERROR_NO_INIT;
  }
  if (nbytes == 0) {
    return SA_SUCCESS;
  }

  nframes = snd_pcm_bytes_to_frames(s->output_unit, nbytes);
  while(nframes>0) {
    if (s->resumed) {
      avail = snd_pcm_avail_update(s->output_unit);
      frames = snd_pcm_writei(s->output_unit, data, nframes > avail ? avail : nframes);
      avail = snd_pcm_avail_update(s->output_unit);
      s->resumed = avail != 0;
    } else {
      avail = snd_pcm_avail_update(s->output_unit);
      avail = avail < 64 ? 64 : avail;
      frames = snd_pcm_writei(s->output_unit, data, nframes > avail ? avail : nframes);
    }
    if (frames < 0) {
      int r = snd_pcm_recover(s->output_unit, frames, 1);
      if (r < 0) {
        return SA_ERROR_SYSTEM;
      }
    } else {
      size_t bytes = snd_pcm_frames_to_bytes(s->output_unit, frames);
      nframes -= frames;
      data = ((unsigned char *)data) + bytes;
      s->bytes_written += bytes;
    }
  }

  return SA_SUCCESS;
}
Esempio n. 25
0
/**
 * \brief Obtain delay for a running PCM handle
 * \param pcm ordinary PCM handle
 * \param delayp Returned delay in frames
 * \return 0 on success otherwise a negative error code
 *
 * Delay is distance between current application frame position and
 * sound frame position.
 * It's positive and less than buffer size in normal situation,
 * negative on playback underrun and greater than buffer size on
 * capture overrun.
 */
int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp)
{
	int err;
	snd_pcm_sframes_t pdelay, cdelay;

	assert(pcm);
	assert(delayp);
	err = sndo_pcm_check_setup(pcm);
	if (err < 0)
		return err;
	if (pcm->playback)
		err = snd_pcm_avail_update(pcm->playback);
	if (err >= 0 && pcm->capture)
		err = snd_pcm_avail_update(pcm->capture);
	if (err >= 0 && pcm->playback)
		err = snd_pcm_delay(pcm->playback, &pdelay);
	if (err >= 0 && pcm->capture)
		err = snd_pcm_delay(pcm->capture, &cdelay);
	if (pdelay > cdelay)
		pdelay = cdelay;
	*delayp = pdelay;
	return err;
}
Esempio n. 26
0
unsigned long SoundGetBytesBuffered(void)
{
 unsigned long l;

 if(handle == NULL)                                 // failed to open?
  return SOUNDSIZE;
 l = snd_pcm_avail_update(handle);
 if(l<0) return 0;
 if(l<buffer_size/2)                                 // can we write in at least the half of fragments?
      l=SOUNDSIZE;                                   // -> no? wait
 else l=0;                                           // -> else go on

 return l;
}
Esempio n. 27
0
static void *peeper(void *data)
{
	int thread_no = (long)data;
	snd_pcm_sframes_t val;
	snd_pcm_status_t *stat;
	snd_htimestamp_t tstamp;
	int mode = running_mode, err;

	snd_pcm_status_alloca(&stat);

	while (running) {
		if (running_mode == MODE_RANDOM)
			mode = rand() % MODE_RANDOM;
		switch (mode) {
		case MODE_AVAIL_UPDATE:
			val = snd_pcm_avail_update(pcm);
			err = 0;
			break;
		case MODE_STATUS:
			err = snd_pcm_status(pcm, stat);
			val = snd_pcm_status_get_avail(stat);
			break;
		case MODE_HWSYNC:
			err = snd_pcm_hwsync(pcm);
			break;
		case MODE_TIMESTAMP:
			err = snd_pcm_htimestamp(pcm, (snd_pcm_uframes_t *)&val,
						 &tstamp);
			break;
		default:
			err = snd_pcm_delay(pcm, &val);
			break;
		}

		if (quiet)
			continue;
		if (running_mode == MODE_RANDOM) {
			fprintf(stderr, "%d%c%s", thread_no, mode_suffix[mode],
				err ? "!" : "");
		} else {
			if (show_value && mode != MODE_HWSYNC)
				fprintf(stderr, "\r%d     ", (int)val);
			else
				fprintf(stderr, "%d%s", thread_no,
					err ? "!" : "");
		}
	}
	return NULL;
}
Esempio n. 28
0
static void async_callback(snd_async_handler_t *ahandler)
{
        snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
        struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
        signed short *samples = data->samples;
        snd_pcm_channel_area_t *areas = data->areas;
        snd_pcm_sframes_t avail;
        int err;
        
        avail = snd_pcm_avail_update(handle);
        while (avail >= period_size) {
                generate_sine(areas, 0, period_size, &data->phase);
                err = snd_pcm_writei(handle, samples, period_size);
                if (err < 0) {
                        printf("Initial write error: %s\n", snd_strerror(err));
                        exit(EXIT_FAILURE);
                }
                if (err != period_size) {
                        printf("Initial write error: written %i expected %li\n", err, period_size);
                        exit(EXIT_FAILURE);
                }
                avail = snd_pcm_avail_update(handle);
        }
}
Esempio n. 29
0
int snd_pcm_avail_delay(snd_pcm_t *pcm,
			snd_pcm_sframes_t *availp,
			snd_pcm_sframes_t *delayp)
{
	int err;
	snd_pcm_sframes_t val;

	err = snd_pcm_delay(pcm, delayp);
	if (err < 0)
		return err;
	val = snd_pcm_avail_update(pcm);
	if (val < 0)
		return (int)val;
	*availp = val;
	return 0;
}
Esempio n. 30
0
static bool
safeUpdate(snd_pcm_t *handle, int &samples)
{
    samples = snd_pcm_avail_update(handle);

    if (samples < 0) {
        samples = snd_pcm_recover(handle, samples, 0);

        if (samples < 0) {
            ERROR("Got unrecoverable error from snd_pcm_avail_update: %s", snd_strerror(samples));
            return false;
        }
    }

    return true;
}