Hi,

i got this code constructed from an example i found googling.

What i basically want is to initialise some settings and then
i'd like to capture some PCM to a buffer.  This should be
repeatable, i want to initialise ONCE and call a capture
function whenever i need some data.
It is perfectly ok, if the data buffers that are captured are
not consecutive.

The code basically works, but whenever i try to capture the
buffer a SECOND time, the whole program crashes.


Has anybody got a hint for me on what could be wrong?


Thanks for any hints,
Torsten.
#define _GNU_SOURCE
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <alsa/asoundlib.h>
#include <sys/signal.h>

#include "sound.h"
#include "settings.h"

#define QWE	fprintf(stderr, "File %s, Line %i\n", __FILE__, __LINE__)


snd_pcm_t *pcm_handle;
snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
snd_pcm_hw_params_t* hwparams;
char *pcm_name = "default";

int rate = 44100; /* Sample rate */
int exact_rate;   /* Sample rate returned by */
                      /* snd_pcm_hw_params_set_rate_near */ 
int dir;          /* exact_rate == rate --> dir = 0 */
                      /* exact_rate < rate  --> dir = -1 */
                      /* exact_rate > rate  --> dir = 1 */
int periods = 2;       /* Number of periods */
int periodsize = 4*SAMPLES; /* Periodsize (bytes) */

unsigned char *data;
int pcmreturn, l1, l2;
short s1, s2;
int frames;

snd_pcm_state_t sss;


static void show(snd_pcm_state_t* s) {
	switch(*s) {
		case SND_PCM_STATE_OPEN:
			printf("open\n");
			break;

		case SND_PCM_STATE_SETUP:
			printf("SETUP\n");
			break;

		case SND_PCM_STATE_PREPARED:
			printf("PREPARED\n");
			break;

		case SND_PCM_STATE_RUNNING:
			printf("RUNNING\n");
			break;

		case SND_PCM_STATE_XRUN:
			printf("XRUN\n");
			break;

		case SND_PCM_STATE_DRAINING:
			printf("DRAINING\n");
			break;

		case SND_PCM_STATE_PAUSED:
			printf("PAUSED\n");
			break;

		case SND_PCM_STATE_SUSPENDED:
			printf("SUSPENDED\n");
			break;
	}
}

unsigned char* sound_get_data(void) {
	return data;
}

int sound_init(void) {
	pcm_name = strdup("plughw:0,0");
	snd_pcm_hw_params_alloca(&hwparams);

    if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) {
      fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
      return(-1);
    }

    /* Init hwparams with full configuration space */
    if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
      fprintf(stderr, "Can not configure this PCM device.\n");
      return(-1);
    }

    if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
      fprintf(stderr, "Error setting access.\n");
      return(-1);
    }
  
    /* Set sample format */
    if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {
      fprintf(stderr, "Error setting format.\n");
      return(-1);
    }

    /* Set sample rate. If the exact rate is not supported */
    /* by the hardware, use nearest possible rate.         */ 
    exact_rate = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, &dir);
    if (dir != 0) {
      fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n"
                       "==> Using %d Hz instead.\n", rate, exact_rate);
    }

    /* Set number of channels */
    if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0) {
      fprintf(stderr, "Error setting channels.\n");
      return(-1);
    }

    /* Set number of periods. Periods used to be called fragments. */ 
    if (snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) {
      fprintf(stderr, "Error setting periods.\n");
      return(-1);
    }

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

    /* Apply HW parameter settings to */
    /* PCM device and prepare device  */
    if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) {
      fprintf(stderr, "Error setting HW params.\n");
      return(-1);
    }

    data = (unsigned char *)calloc(periodsize*periods*4, 0);
    frames = periodsize >> 2;

QWE;
//    snd_pcm_start(pcm_handle);

	sss = snd_pcm_state(pcm_handle);
	show(&sss);
}


void sound_capture(void) {
QWE;
	show(&sss);
QWE;
	while(pcmreturn = snd_pcm_readi(pcm_handle, data, frames), pcmreturn < 0) {
	    snd_pcm_prepare(pcm_handle);
		QWE;
	}
QWE;
	show(&sss);
QWE;
	snd_pcm_drop(pcm_handle);
QWE;
	show(&sss);
QWE;
	printf("pcmreturn %i\nperiodsize %i\n", pcmreturn, periodsize); // */
QWE;
	show(&sss);

}

Reply via email to