"snd_pcm_set_period_size" is returning chunk size as zero - alsa

I am calling "snd_pcm_get_period_size" and it is returning chunk size as zero.
My configuration is:-
Number of Channels is 2
SamplingRate is 48000
InterleaveFlag is 1
Format is E_ALSA_PCM_RECORD_FORMAT_S16_LE
PeriodSize is 2000
BufferSize is 4000
SoundCardname is hw:2,1,0.
My log is as follows:
DBG::ALLGO::alsa_pcm_recorder_init::46::++Entered.
DBG::ALLGO::alsa_pcm_recorder_init::47::param1::eFormat=2.
DBG::ALLGO::alsa_pcm_recorder_init::48::param2::uiNumChannels=2.
DBG::ALLGO::alsa_pcm_recorder_init::49::param3::uiSamplingRate=48000.
DBG::ALLGO::alsa_pcm_recorder_init::50::param4::bInterleaveFlag=1.
DBG::ALLGO::alsa_pcm_recorder_init::51::param5::uiPeriodSize=2000.
DBG::ALLGO::alsa_pcm_recorder_init::52::param6::uiBufferSize=4000.
DBG::ALLGO::alsa_pcm_recorder_init::53::param7::acSndCardname=hw:1,1.
DBG::ALLGO::alsa_pcm_recorder_init::148::psCaptureHandle->format = 2
DBG::ALLGO::alsa_pcm_recorder_init::149::psCaptureHandle->channels = 2
DBG::ALLGO::alsa_pcm_recorder_init::150::psCaptureHandle->rate = 48000
DBG::ALLGO::alsa_pcm_recorder_init::151::psCaptureHandle->interleaved
= 1
DBG::ALLGO::alsa_pcm_recorder_init::160::snd_pcm_open for
psCapturehandle is done. handle =0x2382f30.
DBG::ALLGO::alsa_pcm_recorder_init::170::snd_pcm_info for
psaptureHandle is done.
DBG::ALLGO::alsa_pcm_recorder_init::179::psCaptureHandle->audiobuf
addr 237a9d0
DBG::ALLGO::set_recording_params::36::++Entered.
ERR::ALLGO::set_recording_params::129::
period time=0 period frames=2000
ERR::ALLGO::set_recording_params::146::
buffer time=0 buffer frames=4000
ERR::ALLGO::set_recording_params::160::chunk size=0 return
value=262144
ERR::ALLGO::set_recording_params::163::buffer size=0 return
value=524288
ERR::ALLGO::set_recording_params::168::ERROR::Can't use period equal
to buffer size (0 == 0)
ERR::ALLGO::alsa_pcm_recorder_init::184::ERROR::set_recording_params
failed.
DBG::ALLGO::alsa_pcm_recorder_uninit::274::++Entered.
DBG::ALLGO::alsa_pcm_recorder_uninit::293::
snd_pcm_drain done.
DBG::ALLGO::alsa_pcm_recorder_uninit::294::
drain returns 0DBG::ALLGO::alsa_pcm_recorder_uninit::296::
snd_pcm_close done.
DBG::ALLGO::alsa_pcm_recorder_uninit::304::--Exiting.
DBG::ALLGO::alsa_pcm_recorder_init::204::--Exiting.
ERR::ALLGO::mls_plat_audio_init::376::alsa_pcm_recorder_init() failed.
DBG::ALLGO::mls_plat_audio_init::405::--Exited
Can anyone please tell me the reason for why it is happening?

Related

Linux sound programming. How to determine a buffer size in frames?

I'm experimenting with ALSA and came across with the following configuration parameter in this howto, Section 2:
The unit of the buffersize depends on the function. Sometimes it is
given in bytes, sometimes the number of frames has to be specified.
One frame is the sample data vector for all channels. For 16 Bit
stereo data, one frame has a length of four bytes.
/* Set buffer size (in frames). The resulting latency is given by */
/* latency = periodsize * periods / (rate * bytes_per_frame) */
if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize * periods)>>2) < 0) {
fprintf(stderr, "Error setting buffersize.\n");
return(-1);
}
I don't understand this For 16 Bit stereo data, one frame has a length
of four bytes
Why is it four? Does it follow by the number of channels: 2? I mean earlier they configured it as follows:
/* Set number of channels */
if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0) {
fprintf(stderr, "Error setting channels.\n");
return(-1);
}
How about if my acoustic system contains 4 outputs? Or 6? Does it mean that I have to configre it to 16 Bit * 4 and 16 Bit * 6 correspondingly?
Why is it four? Does it follow by the number of channels: 2?
Yes, according to mentioned earlier:
One frame is the sample data vector for all channels.
So for stereo 16 bit data, there are two (left and right) channels of 16 bits (=2 bytes) each, so that totals to 4 bytes per frame.

How can I flush/empty my UART(RX) each time before I receive a new message?

const int rxBytes = uart_read_bytes(UART_NUM_0, data, RX_BUF_SIZE, 10 / portTICK_RATE_MS);
To flush input data you can read from the uart repeatedly with a timeout of 0 until zero bytes are returned.

Why is portaudio returning callbacks in bursts?

I'm working with the example recording program that's available here on the portaudio website. And I'm confused about how the frame index is being incremented
Given that the buffer size is 512 frames, and the sample rate is set to 44100Hz, you would assume that the program works through the buffer, returns the callback, and increases the frame index by 512 roughly every 11.6 ms. In main(), I have the program outputting the current frame index every 12ms (as opposed to every 1000ms like in the example, but the rest of my code is identical to theirs), and I assumed that it would increment by 512 with each line of output, but that's not the case. This is a chunk of the output:
index at 12 ms = 0
index at 24 ms = 0
index at 36 ms = 1024
index at 48 ms = 1024
index at 60 ms = 2048
index at 72 ms = 2048
index at 84 ms = 2048
index at 96 ms = 3072
index at 108 ms = 3072
index at 120 ms = 3072
index at 132 ms = 4096
index at 144 ms = 4096
index at 156 ms = 4096
index at 168 ms = 5120
index at 180 ms = 5120
index at 192 ms = 5120
index at 204 ms = 6144
index at 216 ms = 7680
As you can see, this is incrementing in a strange fashion. The index stays at 0 until 36ms, where it then jumps up to 1024, and then the index suddenly increases from 1024 to 2048 at 60ms. The way the index increases is not the way one would it expect it to, and it's also inconsistent. You'll notice that the index takes 24ms to increment from 1024 to 2048, and then 36ms to increment from 2048 to 3072, but then only 12ms to later increment from 6144 to 7680.
My question is, what is happening here and what can I do to get the output happening at a more consistent rate? Is it something to do with the ALSA audio buffer size perhaps?
The PortAudio callback buffer size is not necessarily the host buffer size. The relationship between the two is complex, because not all host APIs support all buffer sizes, but PortAudio will "adapt" to support your requested callback buffer size.
PortAudio computes the host buffer size using an algorithm that incorporates multiple constraints including: the user buffer size, the requested latency, supported host buffer sizes, and heuristics.
For example, if you request a very small callback buffer size, but a large latency, it is likely that PortAudio will use a larger host buffer size, and you may observe bursty callbacks. That looks like what's happening for you: 1024 frame host buffer size, but 512 frame PA callback buffer size.
There is more information in my answer here:
Time between callback calls?
what can I do to get the output happening at a more consistent rate?
Request a smaller latency in the appropriate parameters to Pa_OpenStream().
For some PortAudio host APIs there is also a host-API specific mechanism to force the host buffer size. I'm not sure whether ALSA provides that option.
Alternatively, you can use the paFramesPerBufferUnspecified option, which should result in more regular callbacks at whatever buffer size PortAudio and ALSA negotiate based on your requested latency.
Note that there might be some ALSA-specific or device-specific reason why you're getting 1024 frame host buffers. But I'd try the above first.

Segmentation fault in samplerate conversion function

playmp3() using libmpg123
if (isPaused==0 && mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
{
char * resBuffer=&buffer[0]; //22100=0,5s
buffer = resample(resBuffer,22100,22100);
if((ao_play(dev, (char*)buffer, done)==0)){
return 1;
}
resample() Using avcodec from ffmpeg
#define LENGTH_MS 500 // how many milliseconds of speech to store
#define RATE 44100 // the sampling rate (input)
#define FORMAT PA_SAMPLE_S16NE // sample size: 8 or 16 bits
#define CHANNELS 2 // 1 = mono 2 = stereo
struct AVResampleContext* audio_cntx = 0;
char * resample(char in_buffer[(LENGTH_MS*RATE*16*CHANNELS)/8000],int out_rate,int nsamples)
{
char out_buffer[ sizeof( in_buffer ) * 4];
audio_cntx = av_resample_init( out_rate, //out rate
RATE, //in rate
16, //filter length
10, //phase count
0, //linear FIR filter
1.0 ); //cutoff frequency
assert( audio_cntx && "Failed to create resampling context!");
int samples_consumed;
int samples_output = av_resample( audio_cntx, //resample context
(short*)out_buffer, //buffout
(short*)in_buffer, //buffin
&samples_consumed, //&consumed
nsamples, //nb_samples
sizeof(out_buffer)/2,//lenout
0);//is_last
assert( samples_output > 0 && "Error calling av_resample()!" );
av_resample_close( audio_cntx );
//*resample = malloc(sizeof(out_buffer));
return &out_buffer[0];
}
When i run this code i get 3393 Segmentation fault (core dump created). Why?
For example, the use of pointers is correct?
and 22100 are the samples that are contained in 0.5 seconds of the song?
You have two issues that I can see right off the bat. These are noob questions, but everyone does this at least once, so don't worry!
Check that sizeof( in_buffer ) is giving you the size of the buffer you expect ((LENGTH_MS*RATE*16*CHANNELS)/8000) or the size of the pointer(which would be 2, 4 or 8 depending on your system.) Using sizeof on an array on the stack gives you its total size, because there is no pointer only a buffer. Sizeof an array on the parameter list gives you the size of the pointer even if you use [] on the param list, because there only is a pointer.
Also, returning a stack based buffer is undefined (i.e. will crash), since the stack gets reused on the next function call:
return &out_buffer[0];
Don't do that. Pass in the out buffer already allocated by the caller.

ALSA: Ways to prevent underrun for speaker

I am playing a single channel audio in non-interleaved mode. I am getting underrun when I am writing audio data into speaker : ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred
Here is how I write:
printf("%d",snd_pcm_avail (spkhandle));
ret = snd_pcm_writen(spkhandle, pSpeakerBuf , framesIn18Millisec);
if(ret < 0)
{
snd_pcm_recover(spkhandle, ret, 0);
}
What are the different ways/parameter configurations to prevent ALSA under run ?
(I am using Linux 3.0, ARM )
Edit:
Here is a buffer measurement using snd_pcm_avail() API
snd_pcm_avail = 2304 << snd_pcm_writen call 1 success
snd_pcm_avail = 2160 << snd_pcm_writen call 2 success
snd_pcm_avail = 2016 << snd_pcm_writen call 3 success
snd_pcm_writen error -32 Broken pipe << snd_pcm_writen call 4 failure
ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred << And displays this message
Here is the output that Marko requested for:
snd_output_t* out;
....
// Do alsa parameters init ....
....
snd_output_stdio_attach(&out, stderr, 0);
snd_pcm_dump_sw_setup(spkhandle, out);
tstamp_mode : NONE
period_step : 1
avail_min : 144
period_event : 0
start_threshold : 288
stop_threshold : 2304
silence_threshold: 0
silence_size : 0
boundary : 1207959552
I assume this code runs in a tight loop and is intended to block on snd_pcm_writen(). The sample-rate isn't given; I assume 48kHz since the numbers all divide nicely.
What I think is going here is as follows:
snd_pcm_write() doesn't guarantee to write all frames provided (the return value is only ever checked for error conditions). Judging from the logging of snd_pcm_avail() it's in fact consuming avail_min or 144 frames on each. This is 3ms of audio.
Assuming that audio is not running at this point, after two writes, the number of frames in the buffer is equal to start_threshold - at 288 samples; audio output starts
calls to printf() block, and I seem to remember that snd_pcm_avail() has to synchronise with the audio output hardware and might also block. Since you are now 6ms ahead of the playback, it's entirely possible that the buffer is running dry during the time of the third call of snd_pcm_writen()
In summary, you shouldn't be calling printf() at this point, and you probably need to compensate for fact that snd_pcm_writen() isn't consuming all of the frames in pSpeakerBuf
It is the buffer underrun,You can try increasing the buffer size by explicitly mentioning it in your ~/.asoundrc file ?

Resources