static int
write_alsa_output (char * output_data, int output_size) {
    int err;
    snd_pcm_uframes_t frames;

    while (output_size > 0) {
        frames = snd_pcm_bytes_to_frames(pcm, output_size);
        if ((err = snd_pcm_writei(pcm, output_data, frames)) < 0) {
            if (snd_pcm_state(pcm) == SND_PCM_STATE_XRUN) {
                if ((err = snd_pcm_prepare(pcm)) < 0)
                    printf("snd_pcm_prepare() failed.\r\n");
                alsa_first_time = 1;
                continue;
            }
            return err;
        }

        output_size -= snd_pcm_frames_to_bytes(pcm, err);
        output_data += snd_pcm_frames_to_bytes(pcm, err);
        if (alsa_first_time) {
            alsa_first_time = 0;
            snd_pcm_start(pcm);
        }
    }
    return 0;
}
static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
{
	snd_pcm_file_t *file = pcm->private_data;
	unsigned int channel;
	snd_pcm_t *slave = file->gen.slave;
	int err = _snd_pcm_hw_params(slave, params);
	if (err < 0)
		return err;
	file->buffer_bytes = snd_pcm_frames_to_bytes(slave, slave->buffer_size);
	file->wbuf_size = slave->buffer_size * 2;
	file->wbuf_size_bytes = snd_pcm_frames_to_bytes(slave, file->wbuf_size);
	file->wbuf_used_bytes = 0;
	assert(!file->wbuf);
	file->wbuf = malloc(file->wbuf_size_bytes);
	if (file->wbuf == NULL) {
		snd_pcm_file_hw_free(pcm);
		return -ENOMEM;
	}
	file->wbuf_areas = malloc(sizeof(*file->wbuf_areas) * slave->channels);
	if (file->wbuf_areas == NULL) {
		snd_pcm_file_hw_free(pcm);
		return -ENOMEM;
	}
	file->appl_ptr = file->file_ptr_bytes = 0;
	for (channel = 0; channel < slave->channels; ++channel) {
		snd_pcm_channel_area_t *a = &file->wbuf_areas[channel];
		a->addr = file->wbuf;
		a->first = slave->sample_bits * channel;
		a->step = slave->frame_bits;
	}
	return 0;
}
Beispiel #3
0
static ALuint ALSANoMMapProc(ALvoid *ptr)
{
    ALCdevice *Device = (ALCdevice*)ptr;
    alsa_data *data = (alsa_data*)Device->ExtraData;
    snd_pcm_sframes_t avail;
    char *WritePtr;

    SetRTPriority();

    while(!data->killNow)
    {
        int state = verify_state(data->pcmHandle);
        if(state < 0)
        {
            ERR("Invalid state detected: %s\n", snd_strerror(state));
            aluHandleDisconnect(Device);
            break;
        }

        WritePtr = data->buffer;
        avail = data->size / snd_pcm_frames_to_bytes(data->pcmHandle, 1);
        aluMixData(Device, WritePtr, avail);

        while(avail > 0)
        {
            int ret = snd_pcm_writei(data->pcmHandle, WritePtr, avail);
            switch (ret)
            {
            case -EAGAIN:
                continue;
            case -ESTRPIPE:
            case -EPIPE:
            case -EINTR:
                ret = snd_pcm_recover(data->pcmHandle, ret, 1);
                if(ret < 0)
                    avail = 0;
                break;
            default:
                if (ret >= 0)
                {
                    WritePtr += snd_pcm_frames_to_bytes(data->pcmHandle, ret);
                    avail -= ret;
                }
                break;
            }
            if (ret < 0)
            {
                ret = snd_pcm_prepare(data->pcmHandle);
                if(ret < 0)
                    break;
            }
        }
    }

    return 0;
}
Beispiel #4
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);
}
Beispiel #5
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;
}
bool QAudioOutputPrivate::deviceReady()
{
    if(pullMode) {
        int l = 0;
        int chunks = bytesAvailable/period_size;
        if(chunks==0) {
            bytesAvailable = bytesFree();
            return false;
        }
#ifdef DEBUG_AUDIO
        qDebug()<<"deviceReady() avail="<<bytesAvailable<<" bytes, period size="<<period_size<<" bytes";
        qDebug()<<"deviceReady() no. of chunks that can fit ="<<chunks<<", chunks in bytes ="<<period_size*chunks;
#endif
        int input = period_frames*chunks;
        if(input > (int)buffer_frames)
            input = buffer_frames;
        l = audioSource->read(audioBuffer,snd_pcm_frames_to_bytes(handle, input));
        if(l > 0) {
            // Got some data to output
            if(deviceState != QAudio::ActiveState)
                return true;
            write(audioBuffer,l);
            bytesAvailable = bytesFree();

        } else if(l == 0) {
            // Did not get any data to output
            bytesAvailable = bytesFree();
            if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) {
                // Underrun
                errorState = QAudio::UnderrunError;
                deviceState = QAudio::IdleState;
                emit stateChanged(deviceState);
            }

        } else if(l < 0) {
            close();
            errorState = QAudio::IOError;
            emit stateChanged(deviceState);
        }
    } else
        bytesAvailable = bytesFree();

    if(deviceState != QAudio::ActiveState)
        return true;

    if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
        emit notify();
        elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
        timeStamp.restart();
    }
    return true;
}
Beispiel #7
0
static void alsa_stop_capture(ALCdevice *Device)
{
    alsa_data *data = (alsa_data*)Device->ExtraData;
    ALCuint avail;
    int err;

    /* OpenAL requires access to unread audio after stopping, but ALSA's
     * snd_pcm_drain is unreliable and snd_pcm_drop drops it. Capture what's
     * available now so it'll be available later after the drop. */
    avail = alsa_available_samples(Device);
    if(!data->ring && avail > 0)
    {
        /* The ring buffer implicitly captures when checking availability.
         * Direct access needs to explicitly capture it into temp storage. */
        ALsizei size;
        void *ptr;

        size = snd_pcm_frames_to_bytes(data->pcmHandle, avail);
        ptr = realloc(data->buffer, size);
        if(ptr)
        {
            data->buffer = ptr;
            alsa_capture_samples(Device, data->buffer, avail);
            data->size = size;
        }
    }
    err = snd_pcm_drop(data->pcmHandle);
    if(err < 0)
        ERR("drop failed: %s\n", snd_strerror(err));
    data->doCapture = AL_FALSE;
}
Beispiel #8
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;
}
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);
}
Beispiel #10
0
EmErrorCode AlsaRenderer::Write(const char* buf, uint32_t len)
{
    int off = 0;
    int leftFrames = (len + m_FrameLength - 1) / m_FrameLength;

    while (leftFrames > 0) {
        int written = snd_pcm_writei(m_PcmHandle, buf+off, leftFrames);
        if (written > 0) {
            leftFrames -= written;
            off += snd_pcm_frames_to_bytes(m_PcmHandle, written);
        } else if (written == -EPIPE) {
            if (snd_pcm_prepare(m_PcmHandle) < 0)
                printf("FATAL: snd_pcm_prepare() failed!\n");
        } else if (written == -ESTRPIPE) {
            while ((written = snd_pcm_resume(m_PcmHandle)) == -EAGAIN)
                usleep(100);
            if (written < 0) {
                if ((written = snd_pcm_prepare(m_PcmHandle)) < 0)
                    return ErrorCode::RendererFailedToWrite;
            }
        } else if (written <= 0) {
            printf("writei error / short write\n");
        }
    }

    return ErrorCode::Ok;
}
Beispiel #11
0
qint64 QAudioInputPrivate::read( char *data, qint64 maxlen )
{
    int     rc = -1, count=0;

    if (handle != NULL)
    {
        while(count < 5) {
            int frames = snd_pcm_bytes_to_frames(handle, (int)maxlen);
            int readFrames = snd_pcm_readi(handle, data, frames);

            if (readFrames >= 0) {
                rc = snd_pcm_frames_to_bytes(handle, readFrames);
                qLog(QAudioInput) << QString("read in bytes = %1 (frames=%2)").arg(rc).arg(readFrames).toLatin1().constData();
                break;
            }
            else if ((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
                qLog(QAudioInput) << "ALSA: EAGAIN || EINTR error";
                rc = 0;
                break;
            }
            else {
                if(readFrames == -EPIPE) {
                    qLog(QAudioInput) << "ALSA: underrun!!!";
                    rc = snd_pcm_prepare(handle);
                } else if(readFrames == -ESTRPIPE) {
                    qLog(QAudioInput) << "ALSA: suspend recovery!!!!";
                    rc = snd_pcm_prepare(handle);
                }
                if(rc != 0) break;
            }
            count++;
        }
    }
    return rc;
}
Beispiel #12
0
/* transfer data to audio h/w via normal write */
static void
alsa_write_audio(char* data, int length) {
	snd_pcm_sframes_t written_frames;

	while(length > 0) {
		int frames = snd_pcm_bytes_to_frames(alsa_pcm, length);
		written_frames = snd_pcm_writei(alsa_pcm, data, frames);

		if(written_frames > 0) {
			int written = snd_pcm_frames_to_bytes(alsa_pcm,
			                                      written_frames);
			length -= written;
			data += written;
			alsa_hw_written += written;
		} else {
			int err = alsa_handle_error((int) written_frames);

			if(err < 0) {
				printf("alsa_write_audio(): write error: %s\n",
				       snd_strerror(-err));
				break;
			}
		}
	}
}
void QAudioOutputPrivate::resume()
{
    if(deviceState == QAudio::SuspendedState) {
        int err = 0;

        if(handle) {
            err = snd_pcm_prepare( handle );
            if(err < 0)
                xrun_recovery(err);

            err = snd_pcm_start(handle);
            if(err < 0)
                xrun_recovery(err);

            bytesAvailable = (int)snd_pcm_frames_to_bytes(handle, buffer_frames);
        }
        resuming = true;
        if(pullMode)
            deviceState = QAudio::ActiveState;
        else
            deviceState = QAudio::IdleState;

        errorState = QAudio::NoError;
        timer->start(period_time/1000);
        emit stateChanged(deviceState);
    }
}
Beispiel #14
0
static guint
gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
{
    GstAlsaSink *alsa;
    gint err;
    gint cptr;
    gint16 *ptr = data;

    alsa = GST_ALSA_SINK (asink);

    if (alsa->iec958 && alsa->need_swap) {
        guint i;

        GST_DEBUG_OBJECT (asink, "swapping bytes");
        for (i = 0; i < length / 2; i++) {
            ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
        }
    }

    GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);

    cptr = length / alsa->bytes_per_sample;

    GST_ALSA_SINK_LOCK (asink);
    while (cptr > 0) {
        /* start by doing a blocking wait for free space. Set the timeout
         * to 4 times the period time */
        err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
        if (err < 0) {
            GST_DEBUG_OBJECT (asink, "wait error, %d", err);
        } else {
            GST_DELAY_SINK_LOCK (asink);
            err = snd_pcm_writei (alsa->handle, ptr, cptr);
            GST_DELAY_SINK_UNLOCK (asink);
        }

        GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
        if (err < 0) {
            GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
            if (err == -EAGAIN) {
                continue;
            } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
                goto write_error;
            }
            continue;
        }

        ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
        cptr -= err;
    }
    GST_ALSA_SINK_UNLOCK (asink);

    return length - (cptr * alsa->bytes_per_sample);

write_error:
    {
        GST_ALSA_SINK_UNLOCK (asink);
        return length;              /* skip one period */
    }
}
static void snd_pcm_file_add_frames(snd_pcm_t *pcm, 
				    const snd_pcm_channel_area_t *areas,
				    snd_pcm_uframes_t offset,
				    snd_pcm_uframes_t frames)
{
	snd_pcm_file_t *file = pcm->private_data;
	while (frames > 0) {
		snd_pcm_uframes_t n = frames;
		snd_pcm_uframes_t cont = file->wbuf_size - file->appl_ptr;
		snd_pcm_uframes_t avail = file->wbuf_size - snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes);
		if (n > cont)
			n = cont;
		if (n > avail)
			n = avail;
		snd_pcm_areas_copy(file->wbuf_areas, file->appl_ptr, 
				   areas, offset,
				   pcm->channels, n, pcm->format);
		frames -= n;
		offset += n;
		file->appl_ptr += n;
		if (file->appl_ptr == file->wbuf_size)
			file->appl_ptr = 0;
		file->wbuf_used_bytes += snd_pcm_frames_to_bytes(pcm, n);
		if (file->wbuf_used_bytes > file->buffer_bytes)
			snd_pcm_file_write_bytes(pcm, file->wbuf_used_bytes - file->buffer_bytes);
		assert(file->wbuf_used_bytes < file->wbuf_size_bytes);
	}
}
int
sa_stream_drain(sa_stream_t *s)
{
  if (s == NULL || s->output_unit == NULL) {
    return SA_ERROR_NO_INIT;
  }

  if (snd_pcm_state(s->output_unit) == SND_PCM_STATE_PREPARED) {
    size_t min_samples = 0;
    size_t min_bytes = 0;
    void *buf;

    if (sa_stream_get_min_write(s, &min_samples) < 0)
      return SA_ERROR_SYSTEM;
    min_bytes = snd_pcm_frames_to_bytes(s->output_unit, min_samples);    

    buf = malloc(min_bytes);
    if (!buf)
      return SA_ERROR_SYSTEM;
    memset(buf, 0, min_bytes);
    sa_stream_write(s, buf, min_bytes);
    free(buf);
  }

  if (snd_pcm_state(s->output_unit) != SND_PCM_STATE_RUNNING) {
    return SA_ERROR_INVALID;
  }
  snd_pcm_drain(s->output_unit);
  return SA_SUCCESS;
}
Beispiel #17
0
qint64 OutputALSA::writeAudio(unsigned char *data, qint64 maxSize)
{
    if((maxSize = qMin(maxSize, m_prebuf_size - m_prebuf_fill)) > 0)
    {
        memmove(m_prebuf + m_prebuf_fill, data, maxSize);
        m_prebuf_fill += maxSize;
    }

    snd_pcm_uframes_t l = snd_pcm_bytes_to_frames(pcm_handle, m_prebuf_fill);

    while (l >= m_chunk_size)
    {
        snd_pcm_wait(pcm_handle, 10);
        long m;
        if ((m = alsa_write(m_prebuf, m_chunk_size)) >= 0)
        {
            l -= m;
            m = snd_pcm_frames_to_bytes(pcm_handle, m); // convert frames to bytes
            m_prebuf_fill -= m;
            memmove(m_prebuf, m_prebuf + m, m_prebuf_fill); //move data to begin
        }
        else
            return -1;
    }
    return maxSize;
}
Beispiel #18
0
static int audio_write(audiodevice_t *dev, unsigned char *buf, int cnt) {
	audio_alsa09_t *alsa = (audio_alsa09_t *)dev->data_pcm;
	int len, err;
	
	if (NULL == alsa->handle) return NG;
	
	if (cnt == 0) return 0;
	
	len = snd_pcm_bytes_to_frames(alsa->handle, cnt);
	while(0 > (err = snd_pcm_writei(alsa->handle, buf, len))) {
		if (err == -EPIPE) {
			if (0 > snd_pcm_prepare(alsa->handle)) {
				return -1;
			}
			continue;
		} else if (err == -ESTRPIPE) {
			while(-EAGAIN == (err = snd_pcm_resume(alsa->handle))) {
				sleep(1);
			}
			if (err < 0) {
				if (0 > snd_pcm_prepare(alsa->handle)) {
					return -1;
				}
			}
			continue;
		}
		if (0 > snd_pcm_prepare(alsa->handle)) {
			return -1;
		}
	}
	
	return (snd_pcm_frames_to_bytes(alsa->handle, err));
}
static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
	snd_pcm_file_t *file = pcm->private_data;
	snd_pcm_sframes_t err;
	snd_pcm_uframes_t n;
	
	n = snd_pcm_frames_to_bytes(pcm, frames);
	if (n > file->wbuf_used_bytes)
		frames = snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes);
	err = snd_pcm_rewind(file->gen.slave, frames);
	if (err > 0) {
		file->appl_ptr = (file->appl_ptr - err + file->wbuf_size) % file->wbuf_size;
		n = snd_pcm_frames_to_bytes(pcm, err);
		file->wbuf_used_bytes -= n;
	}
	return err;
}
static snd_pcm_sframes_t snd_pcm_file_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
	snd_pcm_file_t *file = pcm->private_data;
	snd_pcm_sframes_t err;
	snd_pcm_uframes_t n;
	
	n = snd_pcm_frames_to_bytes(pcm, frames);
	if (file->wbuf_used_bytes + n > file->wbuf_size_bytes)
		frames = snd_pcm_bytes_to_frames(pcm, file->wbuf_size_bytes - file->wbuf_used_bytes);
	err = INTERNAL(snd_pcm_forward)(file->gen.slave, frames);
	if (err > 0) {
		file->appl_ptr = (file->appl_ptr + err) % file->wbuf_size;
		n = snd_pcm_frames_to_bytes(pcm, err);
		file->wbuf_used_bytes += n;
	}
	return err;
}
Beispiel #21
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;
            }
        }
    }
Beispiel #22
0
static guint
gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length,
    GstClockTime * timestamp)
{
  GstAlsaSrc *alsa;
  gint err;
  gint cptr;
  guint8 *ptr = data;

  alsa = GST_ALSA_SRC (asrc);

  cptr = length / alsa->bpf;

  GST_ALSA_SRC_LOCK (asrc);
  while (cptr > 0) {
    GST_DELAY_SRC_LOCK (asrc);
    err = snd_pcm_readi (alsa->handle, ptr, cptr);
    GST_DELAY_SRC_UNLOCK (asrc);

    if (err < 0) {
      if (err == -EAGAIN) {
        GST_DEBUG_OBJECT (asrc, "Read error: %s", snd_strerror (err));
        continue;
      } else if (err == -ENODEV) {
        goto device_disappeared;
      } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
        goto read_error;
      }
      continue;
    }

    ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
    cptr -= err;
  }
  GST_ALSA_SRC_UNLOCK (asrc);

  /* if driver timestamps are enabled we need to return this here */
  if (alsa->driver_timestamps && timestamp)
    *timestamp = gst_alsasrc_get_timestamp (alsa);

  return length - (cptr * alsa->bpf);

read_error:
  {
    GST_ALSA_SRC_UNLOCK (asrc);
    return length;              /* skip one period */
  }
device_disappeared:
  {
    GST_ELEMENT_ERROR (asrc, RESOURCE, READ,
        (_("Error recording from audio device. "
                "The device has been disconnected.")), (NULL));
    GST_ALSA_SRC_UNLOCK (asrc);
    return (guint) - 1;
  }
}
Beispiel #23
0
qint64 QAudioInputPrivate::bytesAvailable() const
{
    if ( !handle )
        return 0;

    snd_pcm_sframes_t frames;
    if ( snd_pcm_delay( handle, &frames ) < 0 )
        return 0;

    return snd_pcm_frames_to_bytes( handle, frames );
}
Beispiel #24
0
            size_t write_avail()
            {
               snd_pcm_sframes_t rc = snd_pcm_avail(pcm);
               if (rc < 0)
               {
                  runnable = false;
                  return 0;
               }

               return snd_pcm_frames_to_bytes(pcm, rc) / sizeof(T);
            }
Beispiel #25
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;
}
Beispiel #26
0
static ALCboolean alsa_start_playback(ALCdevice *device)
{
    alsa_data *data = (alsa_data*)device->ExtraData;
    snd_pcm_hw_params_t *hp = NULL;
    snd_pcm_access_t access;
    const char *funcerr;
    int err;

    snd_pcm_hw_params_malloc(&hp);
#define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error
    CHECK(snd_pcm_hw_params_current(data->pcmHandle, hp));
    /* retrieve configuration info */
    CHECK(snd_pcm_hw_params_get_access(hp, &access));
#undef CHECK
    snd_pcm_hw_params_free(hp);
    hp = NULL;

    data->size = snd_pcm_frames_to_bytes(data->pcmHandle, device->UpdateSize);
    if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
    {
        data->buffer = malloc(data->size);
        if(!data->buffer)
        {
            ERR("buffer malloc failed\n");
            return ALC_FALSE;
        }
        data->thread = StartThread(ALSANoMMapProc, device);
    }
    else
    {
        err = snd_pcm_prepare(data->pcmHandle);
        if(err < 0)
        {
            ERR("snd_pcm_prepare(data->pcmHandle) failed: %s\n", snd_strerror(err));
            return ALC_FALSE;
        }
        data->thread = StartThread(ALSAProc, device);
    }
    if(data->thread == NULL)
    {
        ERR("Could not create playback thread\n");
        free(data->buffer);
        data->buffer = NULL;
        return ALC_FALSE;
    }

    return ALC_TRUE;

error:
    ERR("%s failed: %s\n", funcerr, snd_strerror(err));
    if(hp) snd_pcm_hw_params_free(hp);
    return ALC_FALSE;
}
Beispiel #27
0
static size_t alsa_write_avail(void *data)
{
   alsa_t *alsa = (alsa_t*)data;

   snd_pcm_sframes_t avail = snd_pcm_avail(alsa->pcm);
   if (avail < 0)
   {
      //RARCH_WARN("[ALSA]: snd_pcm_avail() failed: %s\n", snd_strerror(avail));
      return alsa->buffer_size;
   }

   return snd_pcm_frames_to_bytes(alsa->pcm, avail);
}
Beispiel #28
0
static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
{
	snd_pcm_file_t *file = pcm->private_data;
	unsigned int channel;
	snd_pcm_t *slave = file->gen.slave;
	int err = _snd_pcm_hw_params_internal(slave, params);
	if (err < 0)
		return err;
	file->buffer_bytes = snd_pcm_frames_to_bytes(slave, slave->buffer_size);
	file->wbuf_size = slave->buffer_size * 2;
	file->wbuf_size_bytes = snd_pcm_frames_to_bytes(slave, file->wbuf_size);
	file->wbuf_used_bytes = 0;
	assert(!file->wbuf);
	file->wbuf = malloc(file->wbuf_size_bytes);
	if (file->wbuf == NULL) {
		snd_pcm_file_hw_free(pcm);
		return -ENOMEM;
	}
	file->wbuf_areas = malloc(sizeof(*file->wbuf_areas) * slave->channels);
	if (file->wbuf_areas == NULL) {
		snd_pcm_file_hw_free(pcm);
		return -ENOMEM;
	}
	file->appl_ptr = file->file_ptr_bytes = 0;
	for (channel = 0; channel < slave->channels; ++channel) {
		snd_pcm_channel_area_t *a = &file->wbuf_areas[channel];
		a->addr = file->wbuf;
		a->first = slave->sample_bits * channel;
		a->step = slave->frame_bits;
	}
	if ((file->fd < 0) && (pcm->stream == SND_PCM_STREAM_PLAYBACK)) {
		err = snd_pcm_file_open_output_file(file);
		if (err < 0) {
			SYSERR("failed opening output file %s", file->fname);
			return err;
		}
	}
	return 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((int)frames > (int)buffer_frames)
        frames = buffer_frames;

    return snd_pcm_frames_to_bytes(handle, frames);
}
Beispiel #30
0
/**************************************************************************
 * 			     wodPlayer_WriteMaxFrags            [internal]
 * Writes the maximum number of frames possible to the DSP and returns
 * the number of frames written.
 */
static int wodPlayer_WriteMaxFrags(WINE_WAVEDEV* wwo, DWORD* frames)
{
    /* Only attempt to write to free frames */
    LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
    DWORD dwLength = snd_pcm_bytes_to_frames(wwo->pcm, lpWaveHdr->dwBufferLength - wwo->dwPartialOffset);
    int toWrite = min(dwLength, *frames);
    int written;

    TRACE("Writing wavehdr %p.%u[%u]\n", lpWaveHdr, wwo->dwPartialOffset, lpWaveHdr->dwBufferLength);

    if (toWrite > 0) {
	written = (wwo->write)(wwo->pcm, lpWaveHdr->lpData + wwo->dwPartialOffset, toWrite);
	if ( written < 0) {
	    /* XRUN occurred. let's try to recover */
	    wine_snd_pcm_recover(wwo->pcm, written, 0);
	    written = (wwo->write)(wwo->pcm, lpWaveHdr->lpData + wwo->dwPartialOffset, toWrite);
	}
	if (written <= 0) {
	    /* still in error */
	    ERR("Error in writing wavehdr. Reason: %s\n", snd_strerror(written));
	    return written;
	}
    } else
	written = 0;

    wwo->dwPartialOffset += snd_pcm_frames_to_bytes(wwo->pcm, written);
    if (wwo->dwPartialOffset + wwo->format.Format.nBlockAlign - 1 >= lpWaveHdr->dwBufferLength) {
	/* this will be used to check if the given wave header has been fully played or not... */
	wwo->dwPartialOffset = lpWaveHdr->dwBufferLength;
	/* If we wrote all current wavehdr, skip to the next one */
	wodPlayer_PlayPtrNext(wwo);
    }
    *frames -= written;
    wwo->dwWrittenTotal += snd_pcm_frames_to_bytes(wwo->pcm, written);
    TRACE("dwWrittenTotal=%u\n", wwo->dwWrittenTotal);

    return written;
}