Re: Sound problems on Realtek ALC272

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Jacob Meuser
Date: Wednesday, July 21, 2010 - 12:25 am

On Wed, Jul 21, 2010 at 10:27:29AM +0400, Dmitrij D. Czarkoff wrote:

I've been told this by a few people now.  unfortunately, I don't have
any idea where the problem is.

can you try running the following?  save it to a file, let's call
it audrops.c then build it with 'make LDFLAGS=-lm audrops'.

let that run for a while, at least as long as it takes for you to
normally hear drops and echos.  start it with simply ./audrops.  it
should play a steady tone.  does it print much?  do you hear drops
and/or echos?

-- 
jakemsr@sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org

/*
 * Copyright (c) 2010 Jacob Meuser <jakemsr@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/audioio.h>
#include <sys/param.h>
#include <sys/time.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <err.h>
#include <stdlib.h>
#include <math.h>

#define DEFAULT_DEVICE	"/dev/audio"

#define AUDIO_BPS(bits)	((bits) <= 8 ? 1 : (((bits) <= 16) ? 2 : 4))

volatile sig_atomic_t quit;
extern char *__progname;

void
usage(void)
{
	fprintf(stderr,
		"Usage: %s [-b blocksize] [-c channels] [-f device]\n"
		"          [-p precision] [-r rate] [-w hiwat]\n",
		__progname);
}

void
sigint(int s)
{
	quit = 1;
}

void
setsig(void)
{
	struct sigaction sa;

	quit = 0;
	sigfillset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	sa.sa_handler = sigint;
	if (sigaction(SIGINT, &sa, NULL) < 0)
		err(1, "sigaction(int) failed");
	if (sigaction(SIGTERM, &sa, NULL) < 0)
		err(1, "sigaction(term) failed");
	if (sigaction(SIGHUP, &sa, NULL) < 0)
		err(1, "sigaction(hup) failed");
}

int
set_params(int fd, u_int precision, u_int rate, u_int channels, u_int hiwat,
    u_int *bpf, size_t *block_size)
{
	audio_info_t info;

	AUDIO_INITINFO(&info);

	info.mode = AUMODE_PLAY;
	info.play.precision = precision;
	info.play.channels = channels;
	info.play.sample_rate = rate;
	info.play.encoding = AUDIO_ENCODING_SLINEAR;
	info.play.block_size = *block_size;

	info.hiwat = hiwat;
	info.lowat = hiwat - 1;

	if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
		warn("AUDIO_SETINFO");
		return 0;
	}

	if (ioctl(fd, AUDIO_GETINFO, &info) < 0) {
		warn("AUDIO_GETINFO");
		return 0;
	}

	if (info.play.precision != precision) {
		warnx("unable to set play precision: tried %u, got %u",
		    precision, info.play.precision);
		return 0;
	}
	if (info.play.channels != channels) {
		warnx("unable to set play channels: tried %u, got %u",
		    channels, info.play.channels);
		return 0;
	}
	if (info.play.sample_rate != rate) {
		warnx("unable to set play sample_rate: tried %u, got %u",
		    rate, info.play.sample_rate);
		return 0;
	}

	*bpf = AUDIO_BPS(info.play.precision) * info.play.channels;
	*block_size = info.play.block_size;

	return 1;
}

int
paint_samples(uint8_t *samples, u_int precision, u_int rate, u_int channels)
{
	float d, m;
	double playfreq = 440.0;
	int16_t v;
	uint8_t *p;
	int i, j;

	m = (1 << (precision - 1)) - 1;
	for (i = 0, p = samples; i < rate; i++) {
		d = m * sinf(((float)i / (float)rate) *
		    (2 * M_PI * playfreq));
		d = rintf(d);
		v = d;

		for (j = 0; j < channels; j++) {
			switch (precision) {
			case 8:
				*p = v;
				p++;
				break;
			case 16:
				*p = (v & 0x00ff) >> 0;
				p++;
				*p = (v & 0xff00) >> 8;
				p++;
				break;
			default:
				printf("invalid precision\n");
				return 0;
			}
		}
	}

	return 1;
}

size_t
run_test(int fd, uint8_t *samples, size_t samples_size, size_t block_size,
    long block_usec)
{
	struct timeval now, last_time, diff;
	uint8_t	*play_buf;
	size_t	total_written = 0;
	int	samples_pos = 0, ret, l, l2;

	play_buf = malloc(block_size);
	if (play_buf == NULL)
		err(1, "play_buf=malloc(%lu)", block_size);

	bcopy(samples, play_buf, block_size);
	samples_pos += block_size;

	gettimeofday(&last_time, NULL);

	while (!quit) {
		ret = write(fd, play_buf, block_size);
		gettimeofday(&now, NULL);
		if (ret != block_size)
			printf("broken write: %d of %lu\n", ret, block_size);
		total_written += (ret > 0) ? ret : 0;
		timersub(&now, &last_time, &diff);
		last_time = now;
		if (diff.tv_usec > block_usec * 2) {
			printf("late return at %ld.%06ld: %ld > %ld\n",
			    now.tv_sec, now.tv_usec, diff.tv_usec, block_usec);
		} else if (diff.tv_usec * 2 < block_usec) {
			printf("early return at %ld.%06ld: %ld < %ld\n",
			    now.tv_sec, now.tv_usec, diff.tv_usec, block_usec);
		}
		if (samples_pos + block_size > samples_size) {
			l = samples_size - samples_pos;
			bcopy(samples + samples_pos, play_buf, l);
			l2 = block_size - l;
			bcopy(samples, play_buf + l, l2);
			samples_pos = l2;
		} else {
			bcopy(samples + samples_pos, play_buf, block_size);
			samples_pos += block_size;
		}
	}

	free(play_buf);

	return(total_written);
}


int
main(int argc, char *argv[])
{
	audio_info_t info;
	struct timeval now, start_time, diff;
	char	dev[MAXPATHLEN];
	unsigned long block_usec, run_usec;
	size_t	block_size = 4096, samples_size, total_written;
	u_int	rate = 48000, channels = 2, precision = 16, hiwat = 2;
	int	fd, bpf, ch, pe, error = 0;
	uint8_t *samples;
	const char *errstr;

	snprintf(dev, sizeof(dev), DEFAULT_DEVICE);

	while ((ch = getopt(argc, argv, "b:c:f:p:r:w:")) != -1) {
		switch (ch) {
		case 'b':
			block_size = (size_t)strtonum(optarg, 32, 32768, &errstr);
			if (errstr != NULL) {
				error++;
				warnx("block_size %s", errstr);
			}
			break;
		case 'c':
			channels = (u_int)strtonum(optarg, 1, 12, &errstr);
			if (errstr != NULL) {
				error++;
				warnx("channels %s", errstr);
			}
			break;
		case 'f':
			snprintf(dev, sizeof(dev), "%s", optarg);
			break;
		case 'p':
			precision = (u_int)strtonum(optarg, 8, 32, &errstr);
			if (errstr != NULL) {
				error++;
				warnx("precision %s", errstr);
			}
			break;
		case 'r':
			rate = (u_int)strtonum(optarg, 4000, 192000, &errstr);
			if (errstr != NULL) {
				error++;
				warnx("sample_rate %s", errstr);
			}
			break;
		case 'w':
			hiwat = (u_int)strtonum(optarg, 2, 4096, &errstr);
			if (errstr != NULL) {
				error++;
				warnx("hiwat %s", errstr);
			}
			break;
		default:
			error++;
			break;
		}
		if (error) {
			usage();
			exit(1);
		}
	}
	argc -= optind;
	argv += optind;

	if ((fd = open(dev, O_WRONLY, 0)) == -1)
		err(1, "open(%s)", dev);

	if (!set_params(fd, precision, rate, channels, hiwat,
	    &bpf, &block_size))
		exit(1);

	samples_size = rate * bpf;
	samples = malloc(samples_size);
	if (samples == NULL)
		err(1, "samples=malloc(%lu)", samples_size);

	if (!paint_samples(samples, precision, rate, channels))
		errx(1, "paint_samples() failed");

	block_usec = 1000000 * (block_size / bpf) / rate;

	printf("pre=%u ch=%u bpf=%d block_size=%lu rate=%u block_usec=%ld\n",
	    precision, channels, bpf, block_size, rate, block_usec);

	setsig();

	gettimeofday(&start_time, NULL);

	total_written = run_test(fd, samples, samples_size, block_size,
	    block_usec);

	gettimeofday(&now, NULL);

	if (ioctl(fd, AUDIO_GETINFO, &info) < 0) {
		warn("AUDIO_GETINFO");
		exit(0);
	}

	if (ioctl(fd, AUDIO_PERROR, &pe) < 0) {
		warn("AUDIO_PERROR");
		exit(0);
	}

	close(fd);

	free(samples);

	timersub(&now, &start_time, &diff);

	printf("pre=%u ch=%u bpf=%d block_size=%lu rate=%u block_usec=%ld\n",
	    precision, channels, bpf, block_size, rate, block_usec);

	printf("bytes written = %lu\n", total_written);
	printf("bytes processed = %u\n", info.play.samples);
	printf("bytes errors = %u\n", pe * bpf);
	printf("bytes buffered = %u\n", info.play.seek);
	printf("%lu == %u ?\n", total_written,
	    info.play.samples + info.play.seek + pe * bpf);
	printf("run time = %ld.%06ld s\n", diff.tv_sec, diff.tv_usec);
	run_usec = diff.tv_sec * 1000000 + diff.tv_usec;
	printf("avg rate = %llu\n", ((unsigned long long)(info.play.samples / bpf) * 1000000) / run_usec);

	exit(0);
}
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
Sound problems on Realtek ALC272, Dmitrij D. Czarkoff, (Tue Jul 20, 11:27 pm)
Re: Sound problems on Realtek ALC272, Jan Stary, (Wed Jul 21, 12:23 am)
Re: Sound problems on Realtek ALC272, Jacob Meuser, (Wed Jul 21, 12:25 am)
Re: Sound problems on Realtek ALC272, Dmitrij D. Czarkoff, (Wed Jul 21, 3:53 am)
Re: Sound problems on Realtek ALC272, Dmitrij D. Czarkoff, (Wed Jul 21, 4:10 am)
Re: Sound problems on Realtek ALC272, Jacob Meuser, (Wed Jul 21, 4:40 am)
Re: Sound problems on Realtek ALC272, Dmitrij D. Czarkoff, (Wed Jul 21, 5:11 am)
Re: Sound problems on Realtek ALC272, Jacob Meuser, (Wed Jul 21, 2:40 pm)
Re: Sound problems on Realtek ALC272, Dmitrij D. Czarkoff, (Wed Jul 21, 10:46 pm)