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; }
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; }
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); }
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; }
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; }
/************************************************************************** * 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); }
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; }
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; }
/* 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); } }
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; }
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; }
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; }
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; } } }
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; } }
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 ); }
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); }
/** 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; }
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; }
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); }
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); }
/************************************************************************** * 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; }