Hallo, currently I am working on sound localization an for this reason I would like to extract - an amount of 1024 samples (contiguous ones) - from a never stopping ring buffer (stop threshold = boundary) - simultanously from two different sound cards with ALSA when I need a set of samples for further processing.
I have already tried the snd_pcm_drain() function but this did not work with my capture stream. Now I am trying a direct MMAP access - call hesync, receive pointer, begin, read sample data, commit. However, the official ALSA example code does not help me a lot because it is only for playback. Additionally I do not know how the capture works an how to properly read from it. I spent very much time on reading the documentations espacially the reference. Nevertheless I stil haven't got the information whether it is possible to demand a certain amount of samples with the simple snd_pcm_readi() function (for just one sound card) if the ring buffer is looping without any stop. Can I be sure that I really receive the latest - lets say 1024 - (stereo) samples and that they have not been overwritten, for example. Does snd_pcm_readi() require a continuous stream? Thank you very much for your answer! Sincerely, TobiU PS: This is my code I would like to use for a simpe data acquisition: #include <alsa/asoundlib.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> #include <alsa/asoundlib.h> #include <sched.h> #include <errno.h> #include <math.h> static unsigned int buffer_time = 110000; /* ring buffer length in us */ static unsigned int period_time = 22000; static unsigned int channels = 2; static unsigned int rate = 48000; static unsigned int format = SND_PCM_FORMAT_S16_LE; static snd_pcm_sframes_t period_size, buffer_size; static snd_pcm_uframes_t wantedframes = 1240; //function to set hardware parameters static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params) { unsigned int rrate, value; snd_pcm_uframes_t size; int err, dir; /* choose all parameters */ err = snd_pcm_hw_params_any(handle, params); if (err < 0) { printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); return err; } /* set hardware resampling, Restrict a configuration space to contain only real hardware rates (1 = enabled). */ err = snd_pcm_hw_params_set_rate_resample(handle, params, 1); if (err < 0) { printf("Resampling setup failed for playback: %s\n", snd_strerror(err)); return err; } /* set the interleaved read/write format */ err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { printf("Access type not available for playback: %s\n", snd_strerror(err)); return err; } /* set the sample format */ err = snd_pcm_hw_params_set_format(handle, params, format); if (err < 0) { printf("Sample format not available for playback: %s\n", snd_strerror(err)); return err; } /* set the count of channels */ err = snd_pcm_hw_params_set_channels(handle, params, channels); if (err < 0) { printf("Channels count 2 not available for capture: %s\n", snd_strerror(err)); return err; } /* set the stream rate */ rrate = rate; err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); if (err < 0) { printf("Rate %iHz not available for capture: %s\n", rate, snd_strerror(err)); return err; } if (rrate != rate) { printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err); return -EINVAL; } /* set the buffer size */ value = buffer_time; dir = 1; err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &value, &dir); if (err < 0) { printf("Unable to set buffer time %i for capture: %s\n", dir, snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_buffer_size(params, &size); if (err < 0) { printf("Unable to get buffer size for capture: %s\n", snd_strerror(err)); return err; } buffer_size = size; printf("buffer size is: %i\n", buffer_size); err = snd_pcm_hw_params_get_buffer_time(params, &value, &dir); if (err < 0) { printf("Unable to get buffer time for capture: %s\n", snd_strerror(err)); return err; } printf("buffer time %i with direction %i\n", value, dir); /* set the period size */ value = period_time; dir = 1; err = snd_pcm_hw_params_set_period_time_near(handle, params, &value, &dir); if (err < 0) { printf("Unable to set period time %i for capture: %s\n", size, snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_period_size(params, &size, &dir); if (err < 0) { printf("Unable to get period size for capture: %s\n", snd_strerror(err)); return err; } period_size = size; printf("period size: %i\n", period_size); err = snd_pcm_hw_params_get_period_time(params, &value, &dir); if (err < 0) { printf("Unable to get period time for capture: %s\n", snd_strerror(err)); return err; } printf("period time %i with direction %i\n", value, dir); /* write the parameters to device */ err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Unable to set hw params for capture: %s\n", snd_strerror(err)); return err; } return 0; } //function to set software parameters static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams) { int err; unsigned int value; snd_pcm_uframes_t size; /* get the current swparams */ err = snd_pcm_sw_params_current(handle, swparams); if (err < 0) { printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err)); return err; } /* start the transfer when the buffer contains period_size */ /* (buffer_size / avail_min) * avail_min */ err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period_size); if (err < 0) { printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err)); return err; } /* allow the transfer when at least period_size samples can be processed */ err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size); if (err < 0) { printf("Unable to set avail min for capture: %s\n", snd_strerror(err)); return err; } /* align all transfers period_size samples */ err = snd_pcm_sw_params_set_xfer_align(handle, swparams, period_size); if (err < 0) { printf("Unable to set transfer align for capture: %s\n", snd_strerror(err)); return err; } err = snd_pcm_sw_params_set_tstamp_mode(handle, swparams, SND_PCM_TSTAMP_MMAP); if (err < 0){ printf("Unable to set timestamp mode for capture: %s\n", snd_strerror(err)); return err; } /*never stopping ring buffer (automatic stop threshold = boundary)*/ err = snd_pcm_sw_params_get_boundary(swparams, &size); if (err < 0){ printf("Unable to get boundary for capture: %s\n", snd_strerror(err)); return err; } printf("boundary: %i frames\n", size); err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, size); //changed on 17 Apr if (err < 0){ printf("Unable to set stop threshold for capture: %s\n", snd_strerror(err)); return err; } err = snd_pcm_sw_params_get_stop_threshold(swparams, &size); //changed on 17 Apr if (err < 0){ printf("Unable to set stop threshold for capture: %s\n", snd_strerror(err)); return err; } printf("stop threshold: %i\n", size); /* write the parameters to the capture device */ err = snd_pcm_sw_params(handle, swparams); if (err < 0) { printf("Unable to set sw params for capture: %s\n", snd_strerror(err)); return err; } return 0; } int main() { //Deklaration von Variablen int z; long loops; int rc; snd_pcm_sframes_t rcsframes; int size; //unsigned char buffer int space; unsigned char *buffer; signed short *shortsamples; snd_pcm_t *handle; snd_pcm_hw_params_t *hwparams; snd_pcm_sw_params_t *swparams; unsigned int val; int dir; snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED; snd_pcm_state_t state; /* Open PCM device for capture */ rc = snd_pcm_open(&handle, "hw:0,0", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open first pcm device: %s\n", snd_strerror(rc)); exit(1); } /* set the hardware parameters and write them to driver */ snd_pcm_hw_params_alloca( &hwparams ); rc = set_hwparams( handle, hwparams ); if (rc < 0) { fprintf(stderr, "unable to set hw parameters for first capture: %s\n", snd_strerror(rc)); exit(1); } /* set the software parameters and write them to driver */ snd_pcm_sw_params_alloca( &swparams ); rc = set_swparams( handle, swparams ); if (rc < 0) { fprintf(stderr, "unable to set sw parameters for first capture: %s\n", snd_strerror(rc)); exit(1); } /*prepare handles for use*/ rc = snd_pcm_prepare(handle); if (rc < 0) { printf("Unable to prepare first capture: %s\n", snd_strerror(rc)); exit(1); } /*wait for handles to be ready for use*/ rc = snd_pcm_wait(handle, 1000); if (rc < 0) { printf("Waiting failed for capture: %s\n", snd_strerror(rc)); exit(1); } space = wantedframes * 4; /* 2 bytes/sample, 2 channels */ buffer = (unsigned char *) malloc(space); rc = snd_pcm_start(handle); if (rc < 0) { fprintf(stderr, "Unable to stsrt capture %s\n", snd_strerror(rc)); exit(1); } /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(hwparams, &val, &dir); loops = 5000000 / val; while (loops > 0) { loops--; printf("state of capture: %i\n", snd_pcm_state(handle)); rcsframes = snd_pcm_readi(handle, buffer, wantedframes); /*if (rcsframes == -EPIPE) { /* EPIPE means overrun / fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rcsframes < 0) { fprintf(stderr,"error from read: %s\n", snd_strerror(rcsframes)); } else if (rcsframes != (int)wantedframes) { fprintf(stderr, "short read, read %d frames\n", rcsframes); }*/ if ((int)rcsframes >= wantedframes) printf("number of read frames: %i\n", (int)rcsframes); else { printf("Failure at read\n"); exit(1); } //write the sample values to stdout shortsamples = (signed short *) buffer; for ( z=0; z<(int)wantedframes; z++) { printf("short1: %d\n", (*(shortsamples+z))); printf("short2: %d\n", (*(shortsamples+z+1))); } printf("Ende eines Satzes\n"); printf("state of capture: %i\n",snd_pcm_state(handle) ); sleep(0.6); } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; } -- Echte DSL-Flatrate dauerhaft für 0,- Euro*! "Feel free" mit GMX DSL! http://www.gmx.net/de/go/dsl ------------------------------------------------------- This SF.Net email is sponsored by xPML, a groundbreaking scripting language that extends applications into web and mobile media. Attend the live webcast and join the prime developer group breaking into this new coding territory! http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 _______________________________________________ Alsa-user mailing list Alsa-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-user