static void playback_go(int fd, size_t loaded, off64_t count, int rtype, char *name) { int l, r; off64_t written = 0; off64_t c; set_params(); while (loaded > chunk_bytes && written < count) { if (pcm_write(audiobuf + written, chunk_size) <= 0) return; written += chunk_bytes; loaded -= chunk_bytes; } if (written > 0 && loaded > 0) memmove(audiobuf, audiobuf + written, loaded); l = loaded; while (written < count) { do { c = count - written; if (c > chunk_bytes) c = chunk_bytes; c -= l; if (c == 0) break; r = safe_read(fd, audiobuf + l, c); if (r < 0) { perror(name); exit(EXIT_FAILURE); } fdcount += r; if (r == 0) break; l += r; } while ((size_t)l < chunk_bytes); l = l * 8 / bits_per_frame; r = pcm_write(audiobuf, l); if (r != l) break; r = r * bits_per_frame / 8; written += r; l = 0; } snd_pcm_nonblock(handle, 0); snd_pcm_drain(handle); snd_pcm_nonblock(handle, nonblock); }
static gint gst_tinyalsa_sink_write (GstAudioSink * asink, gpointer data, guint length) { GstTinyalsaSink *sink = GST_TINYALSA_SINK (asink); int ret; again: GST_DEBUG_OBJECT (sink, "Starting write"); ret = pcm_write (sink->pcm, data, length); if (ret == -EPIPE) { GST_WARNING_OBJECT (sink, "Got an underrun"); if (pcm_prepare (sink->pcm) < 0) { GST_ERROR_OBJECT (sink, "Could not prepare device: %s", pcm_get_error (sink->pcm)); return -1; } goto again; } else if (ret < 0) { GST_ERROR_OBJECT (sink, "Could not write data to device: %s", pcm_get_error (sink->pcm)); return -1; } GST_DEBUG_OBJECT (sink, "Wrote %u bytes", length); return length; }
static snd_pcm_sframes_t io_playback_transfer(struct snd_pcm_plugin *plugin, const struct snd_pcm_plugin_channel *src_channels, struct snd_pcm_plugin_channel *dst_channels, snd_pcm_uframes_t frames) { if (snd_BUG_ON(!plugin)) return -ENXIO; if (snd_BUG_ON(!src_channels)) return -ENXIO; if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { return pcm_write(plugin->plug, src_channels->area.addr, frames); } else { int channel, channels = plugin->dst_format.channels; void **bufs = (void**)plugin->extra_data; if (snd_BUG_ON(!bufs)) return -ENXIO; for (channel = 0; channel < channels; channel++) { if (src_channels[channel].enabled) bufs[channel] = src_channels[channel].area.addr; else bufs[channel] = NULL; } return pcm_writev(plugin->plug, bufs, frames); } }
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { int ret; struct stream_out *out = (struct stream_out *)stream; pthread_mutex_lock(&out->dev->lock); pthread_mutex_lock(&out->lock); if (out->standby) { ret = start_output_stream(out); if (ret != 0) { goto err; } out->standby = false; } pcm_write(out->pcm, (void *)buffer, bytes); pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->dev->lock); return bytes; err: pthread_mutex_unlock(&out->lock); if (ret != 0) { usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / out_get_sample_rate(&stream->common)); } return bytes; }
/* * Play DSP from WAV file: */ int PlayDSP(DSPFILE *dfile, WAVFILE *wfile) { UInt32 byte_count = (UInt32) wfile->wavinfo.Samples; int bytes; int n; int byte_modulo; int total_bytes; //First determine how many bytes are required for each channel's sample: switch ( wfile->wavinfo.DataBits ) { case 8 : byte_count = 1; break; case 16 : byte_count = 2; break; default : printf("Cannot process %u bit samples\n", (unsigned)wfile->wavinfo.DataBits); return -1; } byte_modulo = byte_count; /* This many bytes per sample */ byte_count = wfile->wavinfo.Samples * byte_modulo; /* Total bytes to process */ total_bytes = byte_count; /* Seek to requested start sample */ sound_lseek(wfile->fd,wfile->StartSample*byte_modulo,SEEK_CUR); for (; byte_count > 0 && wfile->wavinfo.DataBytes > 0; byte_count -= (UInt32) n ) { bytes = (int) ( byte_count > dfile->dspblksiz ? dfile->dspblksiz : byte_count ); if ( bytes > wfile->wavinfo.DataBytes ) /* Size bigger than data chunk? */ bytes = wfile->wavinfo.DataBytes; /* Data chunk only has this much left */ // printf("play databytes:%d bytes:%d n:%d\n",wfile->wavinfo.DataBytes,bytes,n); if ( (n = sound_read(wfile->fd,dfile->dspbuf,bytes)) != bytes ) { if ( n >= 0 ) printf("Unexpected EOF reading samples from WAV file\n"); else printf("Reading samples from WAV file\n"); goto errxit; } // printf("pcm writeing data\n");//treckle if (pcm_write(dfile->dspbuf,n) <= 0) { printf("Writing samples data failed\n"); goto errxit; } // printf("end pcm writeing data\n");//treckle wfile->wavinfo.DataBytes -= (UInt32) bytes; /* We have fewer bytes left to read */ //printf("dspblksize=%d bytes=%d DataBytes=%d\n", dfile->dspblksiz, bytes, wfile->wavinfo.DataBytes); } return 0; /* All samples played successfully */ errxit: return -1; /* Indicate error return */ }
/* * I/O */ int proxy_write(alsa_device_proxy * proxy, const void *data, unsigned int count) { int ret = pcm_write(proxy->pcm, data, count); if (ret == 0) { proxy->transferred += count / proxy->frame_size; } return ret; }
ssize_t muroard_driver_write(int16_t * data, size_t len, enum muroard_blocking blocking) { if ( blocking == MUROARD_BLOCKING_NONE ) return -1; pcm_write(muroard_state_member(driver_vp), data, len); return 0; }
void play_sample(FILE *file, unsigned int device, unsigned int channels, unsigned int rate, unsigned int bits) { struct pcm_config config; struct pcm *pcm0; char *buffer; int size; int num_read; /* channels = 2,period_size = 8092; buffer_size = 8092*4 = 32k channels = 4, period_size = 4096, buffer_size = 4096*8 = 32k channels = 4, period_size = 2048, buffer_size = 2048*8 = 16k channels = 4, period_size = 1024, buffer_size = 1024*8 = 8k */ config.channels = 4; config.rate = rate; config.period_size = 1024;//4096;//2048 config.period_count = 1; if (bits == 32) config.format = PCM_FORMAT_S32_LE; else if (bits == 16) config.format = PCM_FORMAT_S16_LE; config.start_threshold = 0; config.stop_threshold = 0; config.silence_threshold = 0; /*0 is audiocodec, 1 is hdmiaudio, 2 is spdif*/ pcm0 = pcm_open(1, device, PCM_OUT, &config); if (!pcm0 || !pcm_is_ready(pcm0)) { fprintf(stderr, "Unable to open PCM device %u (%s)\n", device, pcm_get_error(pcm0)); return; } size = pcm_get_buffer_size(pcm0); buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %d bytes\n", size); free(buffer); pcm_close(pcm0); return; } size =size; printf("hx-Playing sample:size:%d, %u ch, %u hz, %u bit\n", size, channels, rate, bits); do { num_read = fread(buffer, 1, size, file); if (num_read > 0) { if (pcm_write(pcm0, buffer, num_read)) { fprintf(stderr, "Error playing sample\n"); break; } } } while (num_read > 0); free(buffer); pcm_close(pcm0); }
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { int ret = 0; struct stream_out *out = (struct stream_out *)stream; struct audio_device *adev = out ? out->dev : NULL; if(adev == NULL) return -ENOSYS; ALOGV("%s enter",__func__); pthread_mutex_lock(&out->dev->lock); pthread_mutex_lock(&out->lock); // there is a possibility that the HD interface is open // and normal pcm stream is still active. Feed the new // interface to normal pcm stream if(adev->active_pcm) { if(adev->active_pcm != out->pcm) out->pcm = adev->active_pcm; } if ((out->standby) || (!adev->active_pcm)) { ret = start_output_stream(out); if (ret != 0) { goto err; } out->standby = false; } if(!out->pcm){ ALOGD("%s: null handle to write - device already closed",__func__); goto err; } ret = pcm_write(out->pcm, (void *)buffer, bytes); ALOGVV("%s: pcm_write returned = %d rate = %d",__func__,ret,out->pcm_config.rate); err: pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->dev->lock); if (ret != 0) { uint64_t duration_ms = ((bytes * 1000)/ (audio_stream_frame_size(&stream->common)) / (out_get_sample_rate(&stream->common))); ALOGV("%s : silence written", __func__); usleep(duration_ms * 1000); } ALOGV("%s exit",__func__); return bytes; }
bool AudioPlaybackLocal::doPlaybackOrRecord(android::sp<Buffer>& buffer) { if (buffer->amountToHandle() < (size_t)mSizes) { mSizes = buffer->amountToHandle(); } if (pcm_write(mPcmHandle, buffer->getUnhanledData(), mSizes)) { LOGE("AudioPlaybackLocal error %s", pcm_get_error(mPcmHandle)); return false; } buffer->increaseHandled(mSizes); LOGV("AudioPlaybackLocal::doPlaybackOrRecord %d", buffer->amountHandled()); return true; }
ssize_t TinyAudioStreamOut::write(const void* buffer, size_t bytes) { Mutex::Autolock _l(mLock); if (!::pcm_is_ready(mPcm)) { // This should never happen... return BAD_VALUE; } if (pcm_write(mPcm, buffer, bytes) != 0) LOGE("TinyAudioStreamOut::write() failed: %s\n", ::pcm_get_error(mPcm)); return NO_ERROR; }
EXTERN_TAG int pcm_output_write(char *buf,unsigned size) { int ret = 0; char *data, *data_dst; char *data_src; char outbuf[8192]; int total_len,ouput_len; #ifdef CODE_CALC_VOLUME float vol = get_android_stream_volume(); apply_stream_volume(vol,buf,size); #endif if(size < 64) return 0; if(size > sizeof(outbuf)){ adec_print("write size tooo big %d \n",size); } total_len = size + cached_len; //adec_print("total_len(%d) = + cached_len111(%d)", size, cached_len); data_src = (char *)cache_buffer_bytes; data_dst = (char *)outbuf; /*write_back data from cached_buffer*/ if(cached_len){ memcpy((void *)data_dst, (void *)data_src, cached_len); data_dst += cached_len; } ouput_len = total_len &(~0x3f); data = (char*)buf; memcpy((void *)data_dst, (void *)data, ouput_len-cached_len); data += (ouput_len-cached_len); cached_len = total_len & 0x3f; data_src = (char *)cache_buffer_bytes; /*save data to cached_buffer*/ if(cached_len){ memcpy((void *)data_src, (void *)data, cached_len); } ret = pcm_write(wfd_pcm,outbuf,ouput_len); if(ret < 0 ){ adec_print("pcm_output_write failed ? \n"); } //adec_print("write size %d ,ret %d \n",size,ret); return ret; }
ssize_t hdmi_out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { hdmi_out_t *out = (hdmi_out_t*)stream; struct hdmi_device_t *adev = (struct hdmi_device_t *)out->dev; ssize_t ret; TRACEM("stream=%p buffer=%p bytes=%d", stream, buffer, bytes); if (!out->up) { if(hdmi_out_open_pcm(out)) { ret = -ENOSYS; goto exit; } } if (out->config.channels > 2 && !adev->CEAMap){ channel_remap(stream, buffer, bytes); ret = pcm_write(out->pcm, out->buffcpy, bytes); } else { ret = pcm_write(out->pcm, buffer, bytes); } exit: if (ret != 0) { ALOGE("Error writing to HDMI pcm: %s", pcm_get_error(out->pcm)); hdmi_out_standby((struct audio_stream*)stream); unsigned int usecs = bytes * 1000000 / audio_stream_frame_size((struct audio_stream*)stream) / hdmi_out_get_sample_rate((struct audio_stream*)stream); if (usecs >= 1000000L) { usecs = 999999L; } usleep(usecs); } return bytes; }
static int write_tinyalsa(out123_handle *ao, unsigned char *buf, int bytes) { mpg123_tinyalsa_t* ta = (mpg123_tinyalsa_t*)ao->userptr; if (ta->pcm) { if(pcm_write(ta->pcm, buf, bytes)) { if(!AOQUIET) error("Error playing sample\n"); return -1; } } return bytes; }
static int inner_main(struct tone_generator_config config) { struct pcm_config *pcm_config = &config.pcm_config; struct pcm *pcm; unsigned pos; void *buf; pcm = pcm_open(config.card, config.device, PCM_OUT, pcm_config); if (!pcm) { fprintf(stderr, "Could not open sound card\n"); fprintf(stderr, "%s\n", pcm_get_error(pcm)); return 1; } if (!pcm_is_ready(pcm)) { fprintf(stderr, "Sound card not ready\n"); fprintf(stderr, "%s\n", pcm_get_error(pcm)); return 1; } buf = calloc(config.bits / 8, pcm_config->period_size * pcm_config->channels); if (!buf) { fprintf(stderr, "Could not allocate memory for buffer\n"); return 1; } for (pos=0 ; (!config.duration || (pos < config.duration)) ; pos += pcm_config->period_size) { oscillator_table_render(buf, config.wave_table, pos, pcm_config->period_size, config.wave_scale, pcm_config->channels, config.chan_mask, /* write to all channels */ config.volume, config.bits); if (pcm_write(pcm, buf, pcm_config->channels * pcm_config->period_size * (config.bits/8))) { fprintf(stderr, "Error writing to sound card\n"); fprintf(stderr, "%s\n", pcm_get_error(pcm)); } } pcm_close(pcm); return 0; }
ssize_t AudioALSAPlaybackHandlerBTSCO::write(const void *buffer, size_t bytes) { ALOGV("%s(), buffer = %p, bytes = %d", __FUNCTION__, buffer, bytes); if (mPcm == NULL) { ALOGE("%s(), mPcm == NULL, return", __FUNCTION__); return bytes; } // const -> to non const void *pBuffer = const_cast<void *>(buffer); ASSERT(pBuffer != NULL); // SRC void *pBufferAfterBliSrc = NULL; uint32_t bytesAfterBliSrc = 0; doBliSrc(pBuffer, bytes, &pBufferAfterBliSrc, &bytesAfterBliSrc); // bit conversion void *pBufferAfterBitConvertion = NULL; uint32_t bytesAfterBitConvertion = 0; doBitConversion(pBufferAfterBliSrc, bytesAfterBliSrc, &pBufferAfterBitConvertion, &bytesAfterBitConvertion); // write data to pcm driver WritePcmDumpData(pBufferAfterBitConvertion, bytesAfterBitConvertion); int retval = pcm_write(mPcm, pBufferAfterBitConvertion, bytesAfterBitConvertion); if (retval != 0) { ALOGE("%s(), pcm_write() error, retval = %d", __FUNCTION__, retval); } return bytes; }
ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes) { int period_size; char *use_case; ALOGV("write:: buffer %p, bytes %d", buffer, bytes); snd_pcm_sframes_t n = 0; size_t sent = 0; status_t err; int write_pending = bytes; if((strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) && (strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { mParent->mLock.lock(); /* PCM handle might be closed and reopened immediately to flush * the buffers, recheck and break if PCM handle is valid */ if (mHandle->handle == NULL && mHandle->rxHandle == NULL) { ALOGV("mDevices =0x%x", mDevices); if(mParent->isExtOutDevice(mDevices)) { ALOGV("StreamOut write - mRouteAudioToExtOut = %d ", mParent->mRouteAudioToExtOut); mParent->mRouteAudioToExtOut = true; if(mParent->mExtOutStream == NULL) { mParent->switchExtOut(mDevices); } } ALOGV("write: mHandle->useCase: %s", mHandle->useCase); snd_use_case_get(mHandle->ucMgr, "_verb", (const char **)&use_case); if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)) { strlcpy(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(SND_USE_CASE_VERB_IP_VOICECALL)); } else if(!strcmp(mHandle->useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) { strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI2, sizeof(SND_USE_CASE_MOD_PLAY_MUSIC2)); } else if (!strcmp(mHandle->useCase,SND_USE_CASE_MOD_PLAY_MUSIC)) { strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI, sizeof(SND_USE_CASE_MOD_PLAY_MUSIC)); } else if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) { strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)); } } else { if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) { strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(SND_USE_CASE_MOD_PLAY_VOIP)); } else if(!strcmp(mHandle->useCase,SND_USE_CASE_VERB_HIFI2)) { strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, sizeof(SND_USE_CASE_MOD_PLAY_MUSIC2)); } else if (!strcmp(mHandle->useCase,SND_USE_CASE_VERB_HIFI)) { strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(SND_USE_CASE_MOD_PLAY_MUSIC)); } else if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) { strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)); } } free(use_case); if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { #ifdef QCOM_USBAUDIO_ENABLED if((mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| (mDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)|| (mDevices & AudioSystem::DEVICE_OUT_PROXY)) { mHandle->module->route(mHandle, mDevices , mParent->mode()); }else #endif { mHandle->module->route(mHandle, mDevices , AUDIO_MODE_IN_COMMUNICATION); } #ifdef QCOM_USBAUDIO_ENABLED } else if((mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| (mDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)|| (mDevices & AudioSystem::DEVICE_OUT_PROXY)) { mHandle->module->route(mHandle, mDevices , mParent->mode()); #endif } else { mHandle->module->route(mHandle, mDevices , mParent->mode()); } if (!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI) || !strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI2) || !strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC) || !strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) { snd_use_case_set(mHandle->ucMgr, "_verb", mHandle->useCase); } else { snd_use_case_set(mHandle->ucMgr, "_enamod", mHandle->useCase); } if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { err = mHandle->module->startVoipCall(mHandle); } else mHandle->module->open(mHandle); if(mHandle->handle == NULL) { ALOGE("write:: device open failed"); mParent->mLock.unlock(); return bytes; } #ifdef QCOM_USBAUDIO_ENABLED if((mDevices == AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET)|| (mDevices == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)){ if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { ALOGV("Setting VOIPCALL bit here, musbPlaybackState %d", mParent->musbPlaybackState); mParent->musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL; } else { mParent->startUsbPlaybackIfNotStarted(); ALOGV("enabling music, musbPlaybackState: %d ", mParent->musbPlaybackState); mParent->musbPlaybackState |= USBPLAYBACKBIT_MUSIC; } } #endif } if (mParent->mRouteAudioToExtOut) { mUseCase = mParent->useCaseStringToEnum(mHandle->useCase); if (! (mParent->getExtOutActiveUseCases_l() & mUseCase )){ ALOGD("startPlaybackOnExtOut_l from write :: useCase = %s", mHandle->useCase); status_t err = NO_ERROR; err = mParent->startPlaybackOnExtOut_l(mUseCase); if(err) { ALOGE("startPlaybackOnExtOut_l from write return err = %d", err); mParent->mLock.unlock(); return err; } } } mParent->mLock.unlock(); } #ifdef QCOM_USBAUDIO_ENABLED if(((mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) || (mDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) && (!mParent->musbPlaybackState)) { mParent->mLock.lock(); mParent->startUsbPlaybackIfNotStarted(); ALOGV("Starting playback on USB"); if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL) || !strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)) { ALOGV("Setting VOIPCALL bit here, musbPlaybackState %d", mParent->musbPlaybackState); mParent->musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL; }else{ ALOGV("enabling music, musbPlaybackState: %d ", mParent->musbPlaybackState); mParent->musbPlaybackState |= USBPLAYBACKBIT_MUSIC; } mParent->mLock.unlock(); } #endif period_size = mHandle->periodSize; do { if (write_pending < period_size) { write_pending = period_size; } if((mParent->mVoipStreamCount) && (mHandle->rxHandle != 0)) { n = pcm_write(mHandle->rxHandle, (char *)buffer + sent, period_size); } else if (mHandle->handle != 0){ n = pcm_write(mHandle->handle, (char *)buffer + sent, period_size); } if (n < 0) { mParent->mLock.lock(); if (mHandle->handle != NULL) { ALOGE("pcm_write returned error %d, trying to recover\n", n); pcm_close(mHandle->handle); mHandle->handle = NULL; if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) || (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) { pcm_close(mHandle->rxHandle); mHandle->rxHandle = NULL; mHandle->module->startVoipCall(mHandle); } else { if (mParent->mALSADevice->mADSPState == ADSP_UP_AFTER_SSR) { ALOGD("SSR Case: Call device switch to apply AMIX controls."); mHandle->module->route(mHandle, mDevices , mParent->mode()); // In-case of multiple streams only one stream will be resumed // after resetting mADSPState to ADSP_UP with output device routed mParent->mALSADevice->mADSPState = ADSP_UP; if(mParent->isExtOutDevice(mDevices)) { ALOGV("StreamOut write - mRouteAudioToExtOut = %d ", mParent->mRouteAudioToExtOut); mParent->mRouteAudioToExtOut = true; } } mHandle->module->open(mHandle); } if(mHandle->handle == NULL) { ALOGE("write:: device re-open failed"); mParent->mLock.unlock(); return bytes; } } mParent->mLock.unlock(); continue; } else { mFrameCount += n; sent += static_cast<ssize_t>((period_size)); write_pending -= period_size; } } while ((mHandle->handle||(mHandle->rxHandle && mParent->mVoipStreamCount)) && sent < bytes); return sent; }
ssize_t AudioALSAPlaybackHandlerNormal::write(const void *buffer, size_t bytes) { ALOGV("%s(), buffer = %p, bytes = %d", __FUNCTION__, buffer, bytes); if (mPcm == NULL) { ALOGE("%s(), mPcm == NULL, return", __FUNCTION__); return bytes; } // const -> to non const void *pBuffer = const_cast<void *>(buffer); ASSERT(pBuffer != NULL); #ifdef DEBUG_LATENCY clock_gettime(CLOCK_REALTIME, &mNewtime); latencyTime[0] = calc_time_diff(mNewtime, mOldtime); mOldtime = mNewtime; #endif // stereo to mono for speaker if (mStreamAttributeSource->audio_format == AUDIO_FORMAT_PCM_16_BIT) // AudioMixer will perform stereo to mono when 32-bit { doStereoToMonoConversionIfNeed(pBuffer, bytes); } // post processing (can handle both Q1P16 and Q1P31 by audio_format_t) void *pBufferAfterPostProcessing = NULL; uint32_t bytesAfterPostProcessing = 0; doPostProcessing(pBuffer, bytes, &pBufferAfterPostProcessing, &bytesAfterPostProcessing); // SRC void *pBufferAfterBliSrc = NULL; uint32_t bytesAfterBliSrc = 0; doBliSrc(pBufferAfterPostProcessing, bytesAfterPostProcessing, &pBufferAfterBliSrc, &bytesAfterBliSrc); // bit conversion void *pBufferAfterBitConvertion = NULL; uint32_t bytesAfterBitConvertion = 0; doBitConversion(pBufferAfterBliSrc, bytesAfterBliSrc, &pBufferAfterBitConvertion, &bytesAfterBitConvertion); // data pending void *pBufferAfterPending = NULL; uint32_t bytesAfterpending = 0; dodataPending(pBufferAfterBitConvertion, bytesAfterBitConvertion, &pBufferAfterPending, &bytesAfterpending); // pcm dump WritePcmDumpData(pBufferAfterPending, bytesAfterpending); #ifdef DEBUG_LATENCY clock_gettime(CLOCK_REALTIME, &mNewtime); latencyTime[1] = calc_time_diff(mNewtime, mOldtime); mOldtime = mNewtime; #endif // write data to pcm driver int retval = pcm_write(mPcm, pBufferAfterPending, bytesAfterpending); #ifdef DEBUG_LATENCY clock_gettime(CLOCK_REALTIME, &mNewtime); latencyTime[2] = calc_time_diff(mNewtime, mOldtime); mOldtime = mNewtime; #endif #if 1 // TODO(Harvey, Wendy), temporary disable Voice Unlock until 24bit ready //============Voice UI&Unlock REFERECE============= AudioVUnlockDL *VUnlockhdl = AudioVUnlockDL::getInstance(); if (VUnlockhdl != NULL) { // get remain time //VUnlockhdl->SetDownlinkStartTime(ret_ms); VUnlockhdl->GetFirstDLTime(); //VUnlockhdl->SetInputStandBy(false); if (mStreamAttributeSource->output_devices & AUDIO_DEVICE_OUT_WIRED_HEADSET || mStreamAttributeSource->output_devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { memset((void *)pBufferAfterBitConvertion, 0, bytesAfterBitConvertion); } VUnlockhdl->WriteStreamOutToRing(pBufferAfterBitConvertion, bytesAfterBitConvertion); } //=========================================== #endif if (retval != 0) { ALOGE("%s(), pcm_write() error, retval = %d", __FUNCTION__, retval); } #ifdef DEBUG_LATENCY ALOGD("AudioALSAPlaybackHandlerNormal::write (-) latency_in_us,%1.6lf,%1.6lf,%1.6lf", latencyTime[0], latencyTime[1], latencyTime[2]); #endif return bytes; }
int playTTS (int count) { pcm_write (waveBuffer, count); return 0; }
static int stream_transfer(struct stream_transfer *stream_transfer) { struct dev_stream *stream_sender; struct dev_stream *stream_receiver; int size_transfer = 0; int ret =0; int exit_flag =0; int i =0; short* Srcptr; short* Drcptr; stream_sender = stream_transfer->stream_sender; stream_receiver = stream_transfer->stream_receiver; size_transfer = stream_sender->buf_size; #ifdef START_ZERO_BUFFER /* 消除开头杂音 */ memset(stream_sender->buf, 0, stream_sender->buf_size); pcm_write(stream_receiver->dev, stream_sender->buf, stream_sender->buf_size); #endif while( 1 ){ if ( (!stream_transfer->voice_thread_run_flag) || (exit_flag == 1)){ break; } ret = pcm_read(stream_sender->dev, stream_sender->buf, size_transfer); if (ret != 0) { exit_flag = 1; ALOGE("err: read codec err:%s, ret=%d", strerror(errno), ret); break; } if ( (!stream_transfer->voice_thread_run_flag) || (exit_flag == 1)){ break; } ret = pcm_write(stream_receiver->dev, stream_sender->buf, size_transfer); if (ret != 0) { exit_flag = 1; ALOGE("err: write pcm err:%s, ret=%d", strerror(errno), ret); } if ( (!stream_transfer->voice_thread_run_flag) || (exit_flag == 1)){ break; } if (stream_transfer->record_flag == 1){ //是上行,还是下行. if (stream_transfer->voice_direction == UPSTREAM){ Srcptr = (short*)(stream_sender->buf); Drcptr = (short*)(record_data.record_buf + (record_data.lenwriteup%record_data.record_lenth)); if(record_data.lenwriteup >= record_data.lenwritedown) { memcpy(Drcptr,Srcptr,size_transfer); } else { int i; for(i=0;i<size_transfer/2;i++,Drcptr++) { *Drcptr = (*Drcptr + *Srcptr++)/2; } record_data.lenwrite += size_transfer; // sem_post(&sem_record); } record_data.lenwriteup += size_transfer; //ALOGD("stream is upload"); } else { Srcptr = (short*)(stream_sender->buf); Drcptr = (short*)(record_data.record_buf + (record_data.lenwritedown%record_data.record_lenth)); if(record_data.lenwritedown >= record_data.lenwriteup) { memcpy(Drcptr,Srcptr,size_transfer); } else { for(i=0;i<size_transfer/2;i++,Drcptr++) { *Drcptr = ((int)*Drcptr + (int)(*Srcptr++))/2; } record_data.lenwrite += size_transfer; // sem_post(&sem_record); } record_data.lenwritedown += size_transfer; //ALOGD("stream is download"); } sem_post(&sem_record); } //ALOGD("pcm running ... , type=%d ",stream_sender->type); if ( (!stream_transfer->voice_thread_run_flag) || (exit_flag == 1)){ break; } } return 0; }
void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels, unsigned int rate, unsigned int bits, unsigned int period_size, unsigned int period_count) { struct pcm_config config; struct pcm *pcm; char *buffer; int size; int num_read; memset(&config, 0, sizeof(config)); config.channels = channels; config.rate = rate; config.period_size = period_size; config.period_count = period_count; if (bits == 32) config.format = PCM_FORMAT_S32_LE; else if (bits == 16) config.format = PCM_FORMAT_S16_LE; config.start_threshold = 0; config.stop_threshold = 0; config.silence_threshold = 0; if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) { return; } pcm = pcm_open(card, device, PCM_OUT, &config); if (!pcm || !pcm_is_ready(pcm)) { fprintf(stderr, "Unable to open PCM device %u (%s)\n", device, pcm_get_error(pcm)); return; } size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %d bytes\n", size); free(buffer); pcm_close(pcm); return; } printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits); /* catch ctrl-c to shutdown cleanly */ signal(SIGINT, stream_close); do { num_read = fread(buffer, 1, size, file); if (num_read > 0) { if (pcm_write(pcm, buffer, num_read)) { fprintf(stderr, "Error playing sample\n"); break; } } } while (!close && num_read > 0); free(buffer); pcm_close(pcm); }
int play_file(unsigned rate, unsigned channels, int fd, unsigned count, unsigned flags, const char *device) { struct pcm *pcm; struct mixer *mixer; struct pcm_ctl *ctl = NULL; unsigned bufsize; char *data; long avail; long frames; int nfds = 1; struct snd_xferi x; unsigned offset = 0; int err; static int start = 0; struct pollfd pfd[1]; flags |= PCM_OUT; if (channels == 1) flags |= PCM_MONO; else flags |= PCM_STEREO; if (debug) flags |= DEBUG_ON; else flags |= DEBUG_OFF; pcm = pcm_open(flags, device); if (pcm < 0) return pcm; if (!pcm_ready(pcm)) { pcm_close(pcm); return -EBADFD; } pcm->channels = channels; pcm->rate = rate; pcm->flags = flags; if (set_params(pcm)) { fprintf(stderr, "Aplay:params setting failed\n"); pcm_close(pcm); return -errno; } if (!pcm_flag) { if (pcm_prepare(pcm)) { fprintf(stderr, "Aplay:Failed in pcm_prepare\n"); pcm_close(pcm); return -errno; } while(1); } if (flags & PCM_MMAP) { if (mmap_buffer(pcm)) { fprintf(stderr, "Aplay:params setting failed\n"); pcm_close(pcm); return -errno; } if (pcm_prepare(pcm)) { fprintf(stderr, "Aplay:Failed in pcm_prepare\n"); pcm_close(pcm); return -errno; } bufsize = pcm->period_size; if (debug) fprintf(stderr, "Aplay:bufsize = %d\n", bufsize); data = calloc(1, bufsize); if (!data) { fprintf(stderr, "Aplay:could not allocate %d bytes\n", count); pcm_close(pcm); return -ENOMEM; } pfd[0].fd = pcm->fd; pfd[0].events = POLLOUT; while (read(fd, data, bufsize) == bufsize) { x.buf = data; x.frames = (pcm->flags & PCM_MONO) ? (bufsize / 2) : (bufsize / 4); frames = x.frames; for (;;) { if (!pcm->running) { if (pcm_prepare(pcm)) return --errno; pcm->running = 1; start = 0; } pcm->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL | SNDRV_PCM_SYNC_PTR_AVAIL_MIN;//SNDRV_PCM_SYNC_PTR_HWSYNC; err = sync_ptr(pcm); if (err == EPIPE) { fprintf(stderr, "Aplay:Failed in sync_ptr \n"); /* we failed to make our window -- try to restart */ pcm->underruns++; pcm->running = 0; continue; } avail = pcm_avail(pcm); if (debug) fprintf(stderr, "Aplay:avail 1 = %d frames = %d\n",avail, frames); if (avail < 0) return avail; if (avail < pcm->sw_p->avail_min) { poll(pfd, nfds, TIMEOUT_INFINITE); continue; } if (x.frames > avail) frames = avail; if (debug) { fprintf(stderr, "Aplay:avail = %d frames = %d\n",avail, frames); fprintf(stderr, "Aplay:sync_ptr->s.status.hw_ptr %ld pcm->buffer_size %d sync_ptr->c.control.appl_ptr %ld\n", pcm->sync_ptr->s.status.hw_ptr, pcm->buffer_size, pcm->sync_ptr->c.control.appl_ptr); } err = mmap_transfer(pcm, data , offset, frames); if (err == EPIPE) { fprintf(stderr, "Aplay:Failed in mmap_transfer \n"); /* we failed to make our window -- try to restart */ pcm->underruns++; pcm->running = 0; continue; } x.frames -= frames; pcm->sync_ptr->c.control.appl_ptr += frames; pcm->sync_ptr->flags = 0; err = sync_ptr(pcm); if (err == EPIPE) { fprintf(stderr, "Aplay:Failed in sync_ptr 2 \n"); /* we failed to make our window -- try to restart */ pcm->underruns++; pcm->running = 0; continue; } if (debug) { fprintf(stderr, "Aplay:sync_ptr 2 \n"); fprintf(stderr, "Aplay:sync_ptr->s.status.hw_ptr %ld pcm->buffer_size %d sync_ptr->c.control.appl_ptr %ld\n", pcm->sync_ptr->s.status.hw_ptr, pcm->buffer_size, pcm->sync_ptr->c.control.appl_ptr); } if (pcm->sync_ptr->c.control.appl_ptr >= pcm->sw_p->start_threshold) { if(start) goto xyz; if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)) { err = -errno; if (errno == EPIPE) { fprintf(stderr, "Aplay:Failed in SNDRV_PCM_IOCTL_START\n"); /* we failed to make our window -- try to restart */ pcm->underruns++; pcm->running = 0; continue; } else { fprintf(stderr, "Aplay:Error no %d \n", errno); return -errno; } } else start = 1; } xyz: offset += frames; break; } } } else { if (pcm_prepare(pcm)) { fprintf(stderr, "Aplay:Failed in pcm_prepare\n"); pcm_close(pcm); return -errno; } bufsize = pcm->period_size; if (debug) fprintf(stderr, "Aplay:bufsize = %d\n", bufsize); data = calloc(1, bufsize); if (!data) { fprintf(stderr, "Aplay:could not allocate %d bytes\n", count); pcm_close(pcm); return -ENOMEM; } while (read(fd, data, bufsize) == bufsize) { if (pcm_write(pcm, data, bufsize)){ fprintf(stderr, "Aplay: pcm_write failed\n"); break; } } } fprintf(stderr, "Aplay: Done playing\n"); free(data); pcm_close(pcm); return 0; }
ssize_t AudioALSAPlaybackHandlerSphDL::write(const void *buffer, size_t bytes) { ALOGV("%s(), buffer = %p, bytes = %d", __FUNCTION__, buffer, bytes); if (mPcm == NULL) { ALOGE("%s(), mPcm == NULL, return", __FUNCTION__); return bytes; } // const -> to non const void *pBuffer = const_cast<void *>(buffer); ASSERT(pBuffer != NULL); #ifdef DEBUG_LATENCY clock_gettime(CLOCK_REALTIME, &mNewtime); latencyTime[0] = calc_time_diff(mNewtime, mOldtime); mOldtime = mNewtime; #endif // stereo to mono for speaker if (mStreamAttributeSource->audio_format == AUDIO_FORMAT_PCM_16_BIT) // AudioMixer will perform stereo to mono when 32-bit { doStereoToMonoConversionIfNeed(pBuffer, bytes); } // post processing (can handle both Q1P16 and Q1P31 by audio_format_t) void *pBufferAfterPostProcessing = NULL; uint32_t bytesAfterPostProcessing = 0; doPostProcessing(pBuffer, bytes, &pBufferAfterPostProcessing, &bytesAfterPostProcessing); // SRC void *pBufferAfterBliSrc = NULL; uint32_t bytesAfterBliSrc = 0; doBliSrc(pBufferAfterPostProcessing, bytesAfterPostProcessing, &pBufferAfterBliSrc, &bytesAfterBliSrc); // bit conversion void *pBufferAfterBitConvertion = NULL; uint32_t bytesAfterBitConvertion = 0; doBitConversion(pBufferAfterBliSrc, bytesAfterBliSrc, &pBufferAfterBitConvertion, &bytesAfterBitConvertion); // pcm dump WritePcmDumpData(pBufferAfterBitConvertion, bytesAfterBitConvertion); #ifdef DEBUG_LATENCY clock_gettime(CLOCK_REALTIME, &mNewtime); latencyTime[1] = calc_time_diff(mNewtime, mOldtime); mOldtime = mNewtime; #endif // write data to pcm driver int retval = pcm_write(mPcm, pBufferAfterBitConvertion, bytesAfterBitConvertion); #ifdef DEBUG_LATENCY clock_gettime(CLOCK_REALTIME, &mNewtime); latencyTime[2] = calc_time_diff(mNewtime, mOldtime); mOldtime = mNewtime; #endif if (retval != 0) { ALOGE("%s(), pcm_write() error, retval = %d", __FUNCTION__, retval); } #ifdef DEBUG_LATENCY ALOGD("AudioALSAPlaybackHandlerSphDL::write (-) latency_in_us,%1.6lf,%1.6lf,%1.6lf", latencyTime[0], latencyTime[1], latencyTime[2]); #endif return bytes; }
int play(int argc, char **argv) { int nMixer = -1, nDevice = -1; pcm_config cfg = { channels : 0, rate : 0, period_size : 1024, period_count : 4, format : PCM_FORMAT_S16_LE, start_threshold : 0, stop_threshold : 0, silence_threshold : 0, }; if (argc == 6) { nMixer = atoi(argv[2]); nDevice = atoi(argv[3]); cfg.rate = atoi(argv[4]); cfg.channels = atoi(argv[5]); } if (argc != 6 || nMixer < 0 || nMixer > 7 || nDevice < 0 || cfg.rate <= 0 || cfg.channels <= 0 || cfg.channels > 2) { printf("Usage: ainfo play <card number> <device number> <rate> <channels>\n" "where <card number> is between 0 and 7\n" "<device number> is the device to play on\n" "<rate> is the sampling rate\n" "<channels> is either 1 or 2\n" "NOTE The file to be played is read from stdin\n"); return 0; } pcm *p = pcm_open(nMixer, nDevice, PCM_OUT, &cfg); if (!pcm_is_ready(p)) { printf("Device not ready. Probably due to invalid parameters."); pcm_close(p); return -1; } unsigned bufsize = pcm_get_buffer_size(p); char *data = new char[bufsize]; if (!data) { printf("Could not allocate %d bytes.\n", bufsize); return -1; } while (read(0, data, bufsize) == bufsize) { printf("."); if (pcm_write(p, data, bufsize)) break; } printf("\b.\nFinished.\n"); delete [] data; pcm_close(p); return 0; } int main(int argc, char **argv) { if (argc >= 2) { if (!strcmp(argv[1], "list")) return list(argc, argv); else if (!strcmp(argv[1], "read")) return read(argc, argv); else if (!strcmp(argv[1], "read-range")) return read_range(argc, argv); else if (!strcmp(argv[1], "write")) return write(argc, argv); else if (!strcmp(argv[1], "write-percentage")) return write_percentage(argc, argv); else if (!strcmp(argv[1], "play")) return play(argc, argv); } printf("Usage: audiotest <command>\nwhere <command> is one of:\n" "list, read, read-range, write, write-percentage, play\n"); return 0; }
bool AudioPlayer::threadLoop() { struct pcm_config config; struct pcm *pcm = NULL; bool moreChunks = true; const struct chunk_fmt* chunkFmt = NULL; int bufferSize; const uint8_t* wavData; size_t wavLength; const struct riff_wave_header* wavHeader; if (mCurrentFile == NULL) { ALOGE("mCurrentFile is NULL"); return false; } wavData = (const uint8_t *)mCurrentFile->getDataPtr(); if (!wavData) { ALOGE("Could not access WAV file data"); goto exit; } wavLength = mCurrentFile->getDataLength(); wavHeader = (const struct riff_wave_header *)wavData; if (wavLength < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || (wavHeader->wave_id != ID_WAVE)) { ALOGE("Error: audio file is not a riff/wave file\n"); goto exit; } wavData += sizeof(*wavHeader); wavLength -= sizeof(*wavHeader); do { const struct chunk_header* chunkHeader = (const struct chunk_header*)wavData; if (wavLength < sizeof(*chunkHeader)) { ALOGE("EOF reading chunk headers"); goto exit; } wavData += sizeof(*chunkHeader); wavLength -= sizeof(*chunkHeader); switch (chunkHeader->id) { case ID_FMT: chunkFmt = (const struct chunk_fmt *)wavData; wavData += chunkHeader->sz; wavLength -= chunkHeader->sz; break; case ID_DATA: /* Stop looking for chunks */ moreChunks = 0; break; default: /* Unknown chunk, skip bytes */ wavData += chunkHeader->sz; wavLength -= chunkHeader->sz; } } while (moreChunks); if (!chunkFmt) { ALOGE("format not found in WAV file"); goto exit; } memset(&config, 0, sizeof(config)); config.channels = chunkFmt->num_channels; config.rate = chunkFmt->sample_rate; config.period_size = mPeriodSize; config.period_count = mPeriodCount; config.start_threshold = mPeriodSize / 4; config.stop_threshold = INT_MAX; config.avail_min = config.start_threshold; if (chunkFmt->bits_per_sample != 16) { ALOGE("only 16 bit WAV files are supported"); goto exit; } config.format = PCM_FORMAT_S16_LE; pcm = pcm_open(mCard, mDevice, PCM_OUT, &config); if (!pcm || !pcm_is_ready(pcm)) { ALOGE("Unable to open PCM device (%s)\n", pcm_get_error(pcm)); goto exit; } bufferSize = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); while (wavLength > 0) { if (exitPending()) goto exit; size_t count = bufferSize; if (count > wavLength) count = wavLength; if (pcm_write(pcm, wavData, count)) { ALOGE("pcm_write failed (%s)", pcm_get_error(pcm)); goto exit; } wavData += count; wavLength -= count; } exit: if (pcm) pcm_close(pcm); mCurrentFile->release(); mCurrentFile = NULL; return false; }
/* * I/O */ int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count) { return pcm_write(proxy->pcm, data, count); }
bool audio_play_buffer(audio_t *c, const unsigned char *buffer, size_t size) { return pcm_write(c->pcm, buffer, size) == 0; }
static int stream_transfer(struct stream_transfer *stream_transfer) { struct dev_stream *stream_sender; struct dev_stream *stream_receiver; short* Srcptr; short* Drcptr; int size_transfer = 0; int ret =0; int exit_flag =0; int i=0; stream_sender = stream_transfer->stream_sender; stream_receiver = stream_transfer->stream_receiver; size_transfer = stream_sender->buf_size; #ifdef START_ZERO_BUFFER /* 消除开头杂音 */ memset(stream_sender->buf, 0, stream_sender->buf_size); pcm_write(stream_receiver->dev, stream_sender->buf, stream_sender->buf_size); #endif ret =pcm_wait(stream_sender->dev, 0); ret =pcm_wait(stream_receiver->dev, 0); pcm_stop(stream_receiver->dev); pcm_start(stream_receiver->dev); /* 消除开头pa音 */ memset(stream_sender->buf, 0, stream_sender->buf_size); pcm_write(stream_receiver->dev, stream_sender->buf, stream_sender->buf_size); while( 1 ){ if ( (!stream_transfer->voice_thread_run_flag)){ break; } #if 0 if (SNDRV_PCM_STATE_XRUN == get_pcm_state(stream_sender->dev) ){ //ALOGD("read SNDRV_PCM_STATE_XRUN "); if(ioctl(stream_sender->dev->fd, SNDRV_PCM_IOCTL_PREPARE)){ ALOGE("in read, fail to prepare SNDRV_PCM_STATE_XRUN "); } //usleep(3 * 1000); ret =pcm_wait(stream_sender->dev, 0); //ALOGD("pcm_read, pcm_wait ret=%d", ret); //ALOGD("read after prepare state:%d ",get_pcm_state(stream_sender->dev)); } #endif ret = pcm_read(stream_sender->dev, stream_sender->buf, size_transfer); if (ret != 0) { //exit_flag = 1; ALOGE("err: read codec err:%s, ret=%d", strerror(errno), ret); //break; } if ( (!stream_transfer->voice_thread_run_flag)){ break; } #if 0 if (SNDRV_PCM_STATE_XRUN == get_pcm_state(stream_receiver->dev) ){ //ALOGD("write SNDRV_PCM_STATE_XRUN "); pcm_stop(stream_receiver->dev); usleep(3 * 1000); //ALOGD("write after stop state:%d ",get_pcm_state(stream_receiver->dev)); pcm_start(stream_receiver->dev); ret =pcm_wait(stream_receiver->dev, 0); //ALOGD("pcm_write, pcm_wait ret=%d", ret); //usleep(3 * 1000); //ALOGD("write after prepare state:%d ",get_pcm_state(stream_receiver->dev)); } #endif ret = pcm_write(stream_receiver->dev, stream_sender->buf, size_transfer); if (ret != 0) { //exit_flag = 1; ALOGE("err: write pcm err:%s, ret=%d", strerror(errno), ret); } if ( (!stream_transfer->voice_thread_run_flag)){ break; } if (stream_transfer->record_flag == 1){ //是上行,还是下行. if (stream_transfer->voice_direction == UPSTREAM){ Srcptr = (short*)(stream_sender->buf); Drcptr = (short*)(record_data.record_buf + (record_data.lenwriteup%record_data.record_lenth)); if(record_data.lenwriteup >= record_data.lenwritedown) { memcpy(Drcptr,Srcptr,size_transfer); } else { int i; for(i=0;i<size_transfer/2;i++,Drcptr++) { *Drcptr = (*Drcptr + *Srcptr++)/2; } record_data.lenwrite += size_transfer; } record_data.lenwriteup += size_transfer; //ALOGD("stream is upload"); } else { Srcptr = (short*)(stream_sender->buf); Drcptr = (short*)(record_data.record_buf + (record_data.lenwritedown%record_data.record_lenth)); if(record_data.lenwritedown >= record_data.lenwriteup) { memcpy(Drcptr,Srcptr,size_transfer); } else { for(i=0;i<size_transfer/2;i++,Drcptr++) { *Drcptr = ((int)*Drcptr + (int)(*Srcptr++))/2; } record_data.lenwrite += size_transfer; } record_data.lenwritedown += size_transfer; } sem_post(&g_sem_record); } if ( (!stream_transfer->voice_thread_run_flag)){ break; } } return 0; }
static int play_file(unsigned rate, unsigned channels, int fd, unsigned flags, const char *device, unsigned data_sz) { struct pcm *pcm; struct mixer *mixer; struct pcm_ctl *ctl = NULL; unsigned bufsize; char *data; long avail; long frames; int nfds = 1; struct snd_xferi x; unsigned offset = 0; int err; static int start = 0; struct pollfd pfd[1]; int remainingData = 0; flags |= PCM_OUT; if (channels == 1) flags |= PCM_MONO; else if (channels == 6) flags |= PCM_5POINT1; else flags |= PCM_STEREO; if (debug) flags |= DEBUG_ON; else flags |= DEBUG_OFF; pcm = pcm_open(flags, device); if (pcm < 0) return pcm; if (!pcm_ready(pcm)) { pcm_close(pcm); return -EBADFD; } #ifdef QCOM_COMPRESSED_AUDIO_ENABLED if (compressed) { struct snd_compr_caps compr_cap; struct snd_compr_params compr_params; if (ioctl(pcm->fd, SNDRV_COMPRESS_GET_CAPS, &compr_cap)) { fprintf(stderr, "Aplay: SNDRV_COMPRESS_GET_CAPS, failed Error no %d \n", errno); pcm_close(pcm); return -errno; } if (!period) period = compr_cap.min_fragment_size; switch (get_compressed_format(compr_codec)) { case FORMAT_MP3: compr_params.codec.id = compr_cap.codecs[FORMAT_MP3]; break; case FORMAT_AC3_PASS_THROUGH: compr_params.codec.id = compr_cap.codecs[FORMAT_AC3_PASS_THROUGH]; printf("codec -d = %x\n", compr_params.codec.id); break; default: break; } if (ioctl(pcm->fd, SNDRV_COMPRESS_SET_PARAMS, &compr_params)) { fprintf(stderr, "Aplay: SNDRV_COMPRESS_SET_PARAMS,failed Error no %d \n", errno); pcm_close(pcm); return -errno; } } #endif pcm->channels = channels; pcm->rate = rate; pcm->flags = flags; pcm->format = format; if (set_params(pcm)) { fprintf(stderr, "Aplay:params setting failed\n"); pcm_close(pcm); return -errno; } if (!pcm_flag) { if (pcm_prepare(pcm)) { fprintf(stderr, "Aplay:Failed in pcm_prepare\n"); pcm_close(pcm); return -errno; } if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)) { fprintf(stderr, "Aplay: Hostless IOCTL_START Error no %d \n", errno); pcm_close(pcm); return -errno; } while(1); } remainingData = data_sz; if (flags & PCM_MMAP) { u_int8_t *dst_addr = NULL; struct snd_pcm_sync_ptr *sync_ptr1 = pcm->sync_ptr; if (mmap_buffer(pcm)) { fprintf(stderr, "Aplay:params setting failed\n"); pcm_close(pcm); return -errno; } if (pcm_prepare(pcm)) { fprintf(stderr, "Aplay:Failed in pcm_prepare\n"); pcm_close(pcm); return -errno; } bufsize = pcm->period_size; if (debug) fprintf(stderr, "Aplay:bufsize = %d\n", bufsize); pfd[0].fd = pcm->timer_fd; pfd[0].events = POLLIN; frames = (pcm->flags & PCM_MONO) ? (bufsize / 2) : (bufsize / 4); for (;;) { if (!pcm->running) { if (pcm_prepare(pcm)) { fprintf(stderr, "Aplay:Failed in pcm_prepare\n"); pcm_close(pcm); return -errno; } pcm->running = 1; start = 0; } /* Sync the current Application pointer from the kernel */ pcm->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL | SNDRV_PCM_SYNC_PTR_AVAIL_MIN;//SNDRV_PCM_SYNC_PTR_HWSYNC; err = sync_ptr(pcm); if (err == EPIPE) { fprintf(stderr, "Aplay:Failed in sync_ptr \n"); /* we failed to make our window -- try to restart */ pcm->underruns++; pcm->running = 0; continue; } /* * Check for the available buffer in driver. If available buffer is * less than avail_min we need to wait */ avail = pcm_avail(pcm); if (avail < 0) { fprintf(stderr, "Aplay:Failed in pcm_avail\n"); pcm_close(pcm); return avail; } if (avail < pcm->sw_p->avail_min) { poll(pfd, nfds, TIMEOUT_INFINITE); continue; } /* * Now that we have buffer size greater than avail_min available to * to be written we need to calcutate the buffer offset where we can * start writting. */ dst_addr = dst_address(pcm); if (debug) { fprintf(stderr, "dst_addr = 0x%08x\n", dst_addr); fprintf(stderr, "Aplay:avail = %d frames = %d\n",avail, frames); fprintf(stderr, "Aplay:sync_ptr->s.status.hw_ptr %ld pcm->buffer_size %d sync_ptr->c.control.appl_ptr %ld\n", pcm->sync_ptr->s.status.hw_ptr, pcm->buffer_size, pcm->sync_ptr->c.control.appl_ptr); } /* * Read from the file to the destination buffer in kernel mmaped buffer * This reduces a extra copy of intermediate buffer. */ memset(dst_addr, 0x0, bufsize); if (data_sz && !piped) { if (remainingData < bufsize) { bufsize = remainingData; frames = (pcm->flags & PCM_MONO) ? (remainingData / 2) : (remainingData / 4); } } err = read(fd, dst_addr , bufsize); if (debug) fprintf(stderr, "read %d bytes from file\n", err); if (err <= 0) break; if (data_sz && !piped) { remainingData -= bufsize; if (remainingData <= 0) break; } /* * Increment the application pointer with data written to kernel. * Update kernel with the new sync pointer. */ pcm->sync_ptr->c.control.appl_ptr += frames; pcm->sync_ptr->flags = 0; err = sync_ptr(pcm); if (err == EPIPE) { fprintf(stderr, "Aplay:Failed in sync_ptr 2 \n"); /* we failed to make our window -- try to restart */ pcm->underruns++; pcm->running = 0; continue; } if (debug) { fprintf(stderr, "Aplay:sync_ptr->s.status.hw_ptr %ld sync_ptr->c.control.appl_ptr %ld\n", pcm->sync_ptr->s.status.hw_ptr, pcm->sync_ptr->c.control.appl_ptr); #ifdef QCOM_COMPRESSED_AUDIO_ENABLED if (compressed && start) { struct snd_compr_tstamp tstamp; if (ioctl(pcm->fd, SNDRV_COMPRESS_TSTAMP, &tstamp)) fprintf(stderr, "Aplay: failed SNDRV_COMPRESS_TSTAMP\n"); else fprintf(stderr, "timestamp = %lld\n", tstamp.timestamp); } #endif } /* * If we have reached start threshold of buffer prefill, * its time to start the driver. */ if(start) goto start_done; if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)) { err = -errno; if (errno == EPIPE) { fprintf(stderr, "Aplay:Failed in SNDRV_PCM_IOCTL_START\n"); /* we failed to make our window -- try to restart */ pcm->underruns++; pcm->running = 0; continue; } else { fprintf(stderr, "Aplay:Error no %d \n", errno); pcm_close(pcm); return -errno; } } else start = 1; start_done: offset += frames; } while(1) { pcm->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL | SNDRV_PCM_SYNC_PTR_AVAIL_MIN;//SNDRV_PCM_SYNC_PTR_HWSYNC; sync_ptr(pcm); /* * Check for the available buffer in driver. If available buffer is * less than avail_min we need to wait */ if (pcm->sync_ptr->s.status.hw_ptr >= pcm->sync_ptr->c.control.appl_ptr) { fprintf(stderr, "Aplay:sync_ptr->s.status.hw_ptr %ld sync_ptr->c.control.appl_ptr %ld\n", pcm->sync_ptr->s.status.hw_ptr, pcm->sync_ptr->c.control.appl_ptr); break; } else poll(pfd, nfds, TIMEOUT_INFINITE); } } else { if (pcm_prepare(pcm)) { fprintf(stderr, "Aplay:Failed in pcm_prepare\n"); pcm_close(pcm); return -errno; } bufsize = pcm->period_size; data = calloc(1, bufsize); if (!data) { fprintf(stderr, "Aplay:could not allocate %d bytes\n", bufsize); pcm_close(pcm); return -ENOMEM; } if (data_sz && !piped) { if (remainingData < bufsize) bufsize = remainingData; } while (read(fd, data, bufsize) > 0) { if (pcm_write(pcm, data, bufsize)){ fprintf(stderr, "Aplay: pcm_write failed\n"); free(data); pcm_close(pcm); return -errno; } memset(data, 0, bufsize); if (data_sz && !piped) { remainingData -= bufsize; if (remainingData <= 0) break; if (remainingData < bufsize) bufsize = remainingData; } } free(data); } fprintf(stderr, "Aplay: Done playing\n"); pcm_close(pcm); return 0; }