On Wed, Jul 21, 2010 at 10:27:29AM +0400, Dmitrij D. Czarkoff wrote: > Hello! > > I've got a Realtec ALC272 codec on my netbook under OpenBSD 4.7 release: > > % dmesg | grep azalia > azalia0 at pci0 dev 27 function 0 "Intel 82801GB HD Audio" rev 0x02: apic 4 > int 16 (irq 11) > azalia0: codecs: Realtek ALC272 > audio0 at azalia0 > > While it actually works, it has kind a performance problem - the frequent gaps > and echos on playback. The longer playback lasts, the worse the situation > goes. > > Interestingly, pausing and continuing playing make the situation better for > some time, but after that problem is back. > > The situation is worse with music and is slightly better with video regardless > of audio file codec and player software. > > Any things I can do?
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? -- jake...@sdf.lonestar.org SDF Public Access UNIX System - http://sdf.lonestar.org /* * Copyright (c) 2010 Jacob Meuser <jake...@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); }