Ejemplo n.º 1
0
/**
 * Record
 */
void *record_alsa(struct bat *bat)
{
    int err = 0;
    FILE *fp = NULL;
    struct snd_pcm_container sndpcm;
    struct wav_container wav;
    int size, offset, count, frames;

    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);

    printf("Entering capture thread (ALSA).\n");
    memset(&sndpcm, 0, sizeof(sndpcm));

    if (NULL != bat->capture.device) {
        err = snd_pcm_open(&sndpcm.handle, bat->capture.device,
                           SND_PCM_STREAM_CAPTURE, 0);
        if (err < 0) {
            loge(E_OPENPCMC, "%s(%d)", snd_strerror(err), err);
            goto fail_exit;
        }
    } else {
        loge(E_OPENPCMC, "exit");
        goto fail_exit;
    }

    err = set_snd_pcm_params(bat, &sndpcm);
    if (err != 0)
        goto fail_exit;

    prepare_wav_info(&wav, bat);

    remove(bat->capture.file);
    fp = fopen(bat->capture.file, "w+");
    if (NULL == fp) {
        loge(E_OPENFILEC, "%s", bat->capture.file);
        goto fail_exit;
    }

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
    pthread_cleanup_push(close_handle, sndpcm.handle);
    pthread_cleanup_push(destroy_mem, sndpcm.buffer);
    pthread_cleanup_push((void *)close_file, fp);

    if (fwrite(&wav.header, 1,
               sizeof(wav.header), fp)
            != sizeof(wav.header)) {
        loge(E_WRITEFILE, "header %s(%d)", snd_strerror(err), err);
        goto fail_exit;
    }
    if (fwrite(&wav.format, 1,
               sizeof(wav.format), fp)
            != sizeof(wav.format)) {
        loge(E_WRITEFILE, "format %s(%d)", snd_strerror(err), err);
        goto fail_exit;
    }
    if (fwrite(&wav.chunk, 1,
               sizeof(wav.chunk), fp)
            != sizeof(wav.chunk)) {
        loge(E_WRITEFILE, "chunk %s(%d)", snd_strerror(err), err);
        goto fail_exit;
    }

    count = wav.chunk.length;
    printf("Recording ...\n");
    while (count > 0) {
        size = (count <= sndpcm.period_bytes) ?
               count : sndpcm.period_bytes;
        frames = size * 8
                 / sndpcm.frame_bits;
        offset = 0;
        while (frames > 0) {
            err = snd_pcm_readi(sndpcm.handle,
                                sndpcm.buffer + offset, frames);
            if (err == -EAGAIN || (err >= 0 && err < frames)) {
                snd_pcm_wait(sndpcm.handle, 500);
            } else if (err == -EPIPE) {
                snd_pcm_prepare(sndpcm.handle);
                loge(E_READPCM S_OVERRUN, "%s(%d)",
                     snd_strerror(err), err);
            } else if (err < 0) {
                loge(E_READPCM, "%s(%d)",
                     snd_strerror(err), err);
                goto fail_exit;
            }

            if (err > 0) {
                frames -= err;
                offset += err * sndpcm.frame_bits / 8;
            }
        }

        if (fwrite(sndpcm.buffer, 1, size, fp) != size) {
            loge(E_WRITEFILE, "%s(%d)", snd_strerror(err), err);
            goto fail_exit;
        }
        count -= size;
        bat->periods_played++;

        if (bat->period_limit
                && bat->periods_played >= bat->periods_total)
            break;
    }

    /* Normally we will never reach this part of code (before fail_exit) as
    	this thread will be cancelled by end of play thread. */
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);

    snd_pcm_drain(sndpcm.handle);
    fclose(fp);
    free(sndpcm.buffer);
    snd_pcm_close(sndpcm.handle);
    retval_record = 0;
    pthread_exit(&retval_record);

fail_exit:
    if (fp)
        fclose(fp);
    if (sndpcm.buffer)
        free(sndpcm.buffer);
    if (sndpcm.handle)
        snd_pcm_close(sndpcm.handle);
    retval_record = 1;
    pthread_exit(&retval_record);
}
Ejemplo n.º 2
0
/**
 * Record
 */
void *record_alsa(struct bat *bat)
{
	int err = 0;
	FILE *fp = NULL;
	struct pcm_container sndpcm;
	struct wav_container wav;
	int count;

	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);

	fprintf(bat->log, _("Entering capture thread (ALSA).\n"));

	retval_record = 0;
	memset(&sndpcm, 0, sizeof(sndpcm));

	if (bat->capture.device == NULL) {
		fprintf(bat->err, _("No PCM device for capture: exit\n"));
		retval_record = 1;
		goto exit1;
	}

	err = snd_pcm_open(&sndpcm.handle, bat->capture.device,
			SND_PCM_STREAM_CAPTURE, 0);
	if (err != 0) {
		fprintf(bat->err, _("Cannot open PCM capture device: "));
		fprintf(bat->err, _("%s(%d)\n"), snd_strerror(err), err);
		retval_record = 1;
		goto exit1;
	}

	err = set_snd_pcm_params(bat, &sndpcm);
	if (err != 0) {
		retval_record = 1;
		goto exit2;
	}

	remove(bat->capture.file);
	fp = fopen(bat->capture.file, "w+");
	if (fp == NULL) {
		fprintf(bat->err, _("Cannot open file for capture: %s %d\n"),
				bat->capture.file, -errno);
		retval_record = 1;
		goto exit3;
	}

	prepare_wav_info(&wav, bat);

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
	pthread_cleanup_push(snd_pcm_close, sndpcm.handle);
	pthread_cleanup_push(free, sndpcm.buffer);
	pthread_cleanup_push(fclose, fp);

	err = write_wav_header(fp, &wav, bat);
	if (err != 0) {
		retval_record = 1;
		goto exit4;
	}

	count = wav.chunk.length;
	fprintf(bat->log, _("Recording ...\n"));
	err = read_from_pcm_loop(fp, count, &sndpcm, bat);
	if (err != 0) {
		retval_record = 1;
		goto exit4;
	}

	/* Normally we will never reach this part of code (before fail_exit) as
	   this thread will be cancelled by end of play thread. */
	pthread_cleanup_pop(0);
	pthread_cleanup_pop(0);
	pthread_cleanup_pop(0);

	snd_pcm_drain(sndpcm.handle);

exit4:
	fclose(fp);
exit3:
	free(sndpcm.buffer);
exit2:
	snd_pcm_close(sndpcm.handle);
exit1:
	pthread_exit(&retval_record);
}
Ejemplo n.º 3
0
/**
 * Play
 */
void *playback_alsa(struct bat *bat)
{
    int err = 0;
    struct snd_pcm_container sndpcm;
    int size, offset, count;

    printf("Entering playback thread (ALSA).\n");

    memset(&sndpcm, 0, sizeof(sndpcm));
    if (NULL != bat->playback.device) {
        err = snd_pcm_open(&sndpcm.handle, bat->playback.device,
                           SND_PCM_STREAM_PLAYBACK, 0);
        if (err < 0) {
            loge(E_OPENPCMP, "%s(%d)", snd_strerror(err), err);
            goto fail_exit;
        }
    } else {
        loge(E_NOPCMP, "exit");
        goto fail_exit;
    }

    err = set_snd_pcm_params(bat, &sndpcm);
    if (err != 0)
        goto fail_exit;

    if (bat->playback.file == NULL) {
        printf("Playing generated audio sine wave");
        bat->sinus_duration == 0 ?
        printf(" endlessly\n") : printf("\n");
    } else {
        printf("Playing input audio file: %s\n", bat->playback.file);
        bat->fp = fopen(bat->playback.file, "rb");
        if (bat->fp == NULL) {
            loge(E_OPENFILEC, "%s", bat->playback.file);
            goto fail_exit;
        }
    }

    count = sndpcm.period_bytes; /* playback buffer size */
#ifdef DEBUG
    FILE *sin_file;
    sin_file = fopen("/tmp/sin.wav", "wb");
#endif
    while (1) {
        offset = 0;
        size = count * 8 / sndpcm.frame_bits;

        err = generate_input_data(sndpcm, count, bat);
        if (err < 0)
            goto fail_exit;
        else if (err > 0)
            break;
#ifdef DEBUG
        fwrite(sndpcm.buffer, count * 8 / sndpcm.frame_bits, 4,
               sin_file);
#endif
        if (bat->period_limit
                && bat->periods_played >= bat->periods_total)
            break;

        err = write_to_pcm(size, &sndpcm, offset);
        if (err == -1)
            goto fail_exit;
    }
#ifdef DEBUG
    fclose(sin_file);
#endif
    snd_pcm_drain(sndpcm.handle);
    if (bat->fp)
        fclose(bat->fp);
    free(sndpcm.buffer);
    snd_pcm_close(sndpcm.handle);
    retval_play = 0;
    pthread_exit(&retval_play);

fail_exit:
    if (bat->fp)
        fclose(bat->fp);
    if (sndpcm.buffer)
        free(sndpcm.buffer);
    if (sndpcm.handle)
        snd_pcm_close(sndpcm.handle);
    retval_play = 1;
    pthread_exit(&retval_play);
}
Ejemplo n.º 4
0
/**
 * Play
 */
void *playback_alsa(struct bat *bat)
{
	int err = 0;
	struct pcm_container sndpcm;

	fprintf(bat->log, _("Entering playback thread (ALSA).\n"));

	retval_play = 0;
	memset(&sndpcm, 0, sizeof(sndpcm));

	if (bat->playback.device == NULL) {
		fprintf(bat->err, _("No PCM device for playback: exit\n"));
		retval_play = 1;
		goto exit1;
	}

	err = snd_pcm_open(&sndpcm.handle, bat->playback.device,
			SND_PCM_STREAM_PLAYBACK, 0);
	if (err != 0) {
		fprintf(bat->err, _("Cannot open PCM playback device: "));
		fprintf(bat->err, _("%s(%d)\n"), snd_strerror(err), err);
		retval_play = 1;
		goto exit1;
	}

	err = set_snd_pcm_params(bat, &sndpcm);
	if (err != 0) {
		retval_play = 1;
		goto exit2;
	}

	if (bat->playback.file == NULL) {
		fprintf(bat->log, _("Playing generated audio sine wave"));
		bat->sinus_duration == 0 ?
			fprintf(bat->log, _(" endlessly\n")) :
			fprintf(bat->log, _("\n"));
	} else {
		fprintf(bat->log, _("Playing input audio file: %s\n"),
				bat->playback.file);
		bat->fp = fopen(bat->playback.file, "rb");
		if (bat->fp == NULL) {
			fprintf(bat->err, _("Cannot open file for capture: "));
			fprintf(bat->err, _("%s %d\n"),
					bat->playback.file, -errno);
			retval_play = 1;
			goto exit3;
		}
		/* Skip header */
		err = read_wav_header(bat, bat->playback.file, bat->fp, true);
		if (err != 0) {
			retval_play = 1;
			goto exit4;
		}
	}

	err = write_to_pcm_loop(&sndpcm, bat);
	if (err != 0) {
		retval_play = 1;
		goto exit4;
	}

exit4:
	if (bat->playback.file)
		fclose(bat->fp);
exit3:
	free(sndpcm.buffer);
exit2:
	snd_pcm_close(sndpcm.handle);
exit1:
	pthread_exit(&retval_play);
}