Exemplo n.º 1
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);
}
Exemplo n.º 2
0
static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
{
	int err;
	int bytes = sndpcm->period_bytes; /* playback buffer size */
	int frames = bytes * 8 / sndpcm->frame_bits; /* frame count */
	FILE *fp = NULL;
	struct wav_container wav;
	int bytes_total = 0;

	if (bat->debugplay) {
		fp = fopen(bat->debugplay, "wb");
		if (fp == NULL) {
			fprintf(bat->err, _("Cannot open file for capture: "));
			fprintf(bat->err, _("%s %d\n"), bat->debugplay, -errno);
			return -errno;
		}
		/* leave space for wav header */
		err = fseek(fp, sizeof(wav), SEEK_SET);
		if (err != 0) {
			fprintf(bat->err, _("Seek file error: %d %d\n"),
					err, -errno);
			return -errno;
		}
	}

	while (1) {
		err = generate_input_data(sndpcm, bytes, bat);
		if (err < 0)
			return err;
		else if (err > 0)
			break;

		if (bat->debugplay) {
			err = fwrite(sndpcm->buffer, 1, bytes, fp);
			if (err != bytes) {
				fprintf(bat->err, _("Write file error: "));
				fprintf(bat->err, _("%s(%d)\n"),
						snd_strerror(err), err);
				return -EIO;
			}
			bytes_total += bytes;
		}

		bat->periods_played++;
		if (bat->period_is_limited
				&& bat->periods_played >= bat->periods_total)
			break;

		err = write_to_pcm(sndpcm, frames, bat);
		if (err != 0)
			return err;
	}

	if (bat->debugplay) {
		/* update wav header */
		prepare_wav_info(&wav, bat);
		wav.chunk.length = bytes_total;
		wav.header.length = (wav.chunk.length) + sizeof(wav.chunk)
			+ sizeof(wav.format) + sizeof(wav.header) - 8;

		rewind(fp);
		err = write_wav_header(fp, &wav, bat);
		if (err != 0) {
			fprintf(bat->err, _("Write file error: %s %s(%d)\n"),
					bat->debugplay, snd_strerror(err), err);
			return err;
		}
		fclose(fp);
	}

	snd_pcm_drain(sndpcm->handle);

	return 0;
}