TErrors SalsaStream::read(llaAudioPipe& buffer) { if(pcm_state_ == CLOSED) { LOGGER().warning(E_READ_STREAM, "Attempt to write to a closed stream."); return E_READ_STREAM; } TErrors err; if( (err = updateSettings(buffer)) != E_OK) return err; char *iraw, **niraw; int rc; getRawInputBuffers(buffer, &iraw, &niraw); if(organization_ == SND_PCM_ACCESS_RW_NONINTERLEAVED) { rc = snd_pcm_readn(pcm_, (void**)niraw, buffer.getBufferLength()); } else { rc = snd_pcm_readi(pcm_, (void*)iraw, buffer.getBufferLength()); } setBufferLastWrite(buffer, rc); if (rc == -EPIPE) { /* EPIPE means underrun */ snd_pcm_prepare(pcm_); } else if (rc < 0) { LOGGER().warning(E_READ_STREAM, snd_strerror(rc)); snd_pcm_recover(pcm_, rc, 0); } return E_OK; }
bool readFromInputDevice (AudioBuffer<float>& inputChannelBuffer, const int numSamples) { jassert (numChannelsRunning <= inputChannelBuffer.getNumChannels()); float* const* const data = inputChannelBuffer.getArrayOfWritePointers(); if (isInterleaved) { scratch.ensureSize ((size_t) ((int) sizeof (float) * numSamples * numChannelsRunning), false); scratch.fillWith (0); // (not clearing this data causes warnings in valgrind) auto num = snd_pcm_readi (handle, scratch.getData(), (snd_pcm_uframes_t) numSamples); if (num < 0) { if (num == -(EPIPE)) overrunCount++; if (JUCE_ALSA_FAILED (snd_pcm_recover (handle, (int) num, 1 /* silent */))) return false; } if (num < numSamples) JUCE_ALSA_LOG ("Did not read all samples: num: " << num << ", numSamples: " << numSamples); for (int i = 0; i < numChannelsRunning; ++i) converter->convertSamples (data[i], 0, scratch.getData(), i, numSamples); } else { auto num = snd_pcm_readn (handle, (void**) data, (snd_pcm_uframes_t) numSamples); if (num < 0) { if (num == -(EPIPE)) overrunCount++; if (JUCE_ALSA_FAILED (snd_pcm_recover (handle, (int) num, 1 /* silent */))) return false; } if (num < numSamples) JUCE_ALSA_LOG ("Did not read all samples: num: " << num << ", numSamples: " << numSamples); for (int i = 0; i < numChannelsRunning; ++i) converter->convertSamples (data[i], data[i], numSamples); } return true; }
static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { snd_pcm_file_t *file = pcm->private_data; snd_pcm_channel_area_t areas[pcm->channels]; snd_pcm_sframes_t n; if (file->ifd >= 0) { SNDERR("DEBUG: Noninterleaved read not yet implemented.\n"); return 0; /* TODO: Noninterleaved read */ } n = snd_pcm_readn(file->gen.slave, bufs, size); if (n > 0) { snd_pcm_areas_from_bufs(pcm, areas, bufs); snd_pcm_file_add_frames(pcm, areas, 0, n); } return n; }
bool readFromInputDevice (AudioSampleBuffer& inputChannelBuffer, const int numSamples) { jassert (numChannelsRunning <= inputChannelBuffer.getNumChannels()); float** const data = inputChannelBuffer.getArrayOfChannels(); if (isInterleaved) { scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false); scratch.fillWith (0); // (not clearing this data causes warnings in valgrind) snd_pcm_sframes_t num = snd_pcm_readi (handle, scratch.getData(), numSamples); if (failed (num)) { if (num == -EPIPE) { if (failed (snd_pcm_prepare (handle))) return false; } else if (num != -ESTRPIPE) return false; } for (int i = 0; i < numChannelsRunning; ++i) converter->convertSamples (data[i], 0, scratch.getData(), i, numSamples); } else { snd_pcm_sframes_t num = snd_pcm_readn (handle, (void**) data, numSamples); if (failed (num) && num != -EPIPE && num != -ESTRPIPE) return false; for (int i = 0; i < numChannelsRunning; ++i) converter->convertSamples (data[i], data[i], numSamples); } return true; }
snd_pcm_sframes_t snd_pcm_generic_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { snd_pcm_generic_t *generic = pcm->private_data; return snd_pcm_readn(generic->slave, bufs, size); }
TErrors SalsaStream::connect( llaOutputStream* output, llaAudioPipe& buffer) { TErrors ret = _open(SND_PCM_NONBLOCK); // Update pcm settings if( ret != E_OK || (ret = updateSettings(buffer)) != E_OK ) return ret; if( (ret = output->open()) != E_OK ) { close(); return ret; } int err = 0; snd_pcm_uframes_t avail_min = 0; if(buffer.getBufferLength() < period_size_) { close(); output->close(); LOGGER().error(E_STREAM_CONFIG, "Buffer length must be higher"); return E_STREAM_CONFIG; } else if(buffer.getBufferLength() / period_size_ < 3 ) avail_min = period_size_; else avail_min = ((buffer.getBufferLength()/period_size_)-2)*period_size_; // Set up the input stream for polling ///////////////////////////////////// // This is the same process as for the output. err = snd_pcm_sw_params_malloc(&sw_config_); err = snd_pcm_sw_params_current(pcm_, sw_config_); CHECK_SNDERROR(err, E_STREAM_CONFIG); // err = snd_pcm_sw_params_set_start_threshold (pcm_, sw_config_, 0U ); // CHECK_SNDERROR(err, E_STREAM_CONFIG); err = snd_pcm_sw_params_set_avail_min(pcm_, sw_config_, avail_min ); CHECK_SNDERROR(err, E_STREAM_CONFIG); err = snd_pcm_sw_params(pcm_, sw_config_); CHECK_SNDERROR(err, E_STREAM_CONFIG); snd_pcm_prepare(pcm_); snd_pcm_uframes_t frames; char *iraw, **niraw; while(!buffer.stop() && !buffer.fail()) { snd_pcm_start(pcm_); if ((err = snd_pcm_wait (pcm_, -1)) < 0) { if (err == -EPIPE) { /* EPIPE means xrun */ snd_pcm_prepare(pcm_); } else if (err < 0) { LOGGER().error(E_READ_STREAM, snd_strerror(err)); snd_pcm_sw_params_free(sw_config_); close(); output->close(); return E_READ_STREAM; } } frames = snd_pcm_avail_update(pcm_); if(frames < 0) { LOGGER().error(E_READ_STREAM, snd_strerror(err)); snd_pcm_sw_params_free(sw_config_); close(); output->close(); return E_READ_STREAM; } if(frames > buffer.getBufferLength()) frames = buffer.getBufferLength(); int rc; getRawInputBuffers( buffer, &iraw, &niraw); // read from the stream if(organization_ == SND_PCM_ACCESS_RW_NONINTERLEAVED) { rc = snd_pcm_readn(pcm_, (void**)niraw, frames); } else { rc = snd_pcm_readi(pcm_, (void*)iraw, frames); } // save the number of frames read TSize lastwrite = ((TSize)rc <= buffer.getBufferLength())? rc : buffer.getBufferLength(); setBufferLastWrite(buffer, lastwrite); // detect errors if (rc == -EPIPE) { /* EPIPE means underrun */ snd_pcm_prepare(pcm_); } else if (rc < 0) { LOGGER().warning(E_READ_STREAM, snd_strerror(rc)); snd_pcm_sw_params_free(sw_config_); close(); output->close(); return E_READ_STREAM; } TErrors reterr; if( (reterr=output->write(buffer)) != E_OK ) { snd_pcm_sw_params_free(sw_config_); close(); output->close(); } } snd_pcm_sw_params_free(sw_config_); close(); output->close(); return E_OK; }