+/* sound test */
+#include <sys/soundcard.h>
+#include <pthread.h>
+
+static int snd_test_l, snd_test_r, snd_test_quit;
+static pthread_cond_t snd_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t snd_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void *sound_thread(void *arg)
+{
+ int i, ret, randfd, dspfd;
+ int frag, bits, stereo, rate;
+ short buf[8*1024];//2*22050 / 10];
+
+ randfd = open("/dev/urandom", O_RDONLY);
+ if (randfd == -1) {
+ perror("open(\"/dev/urandom\")");
+ return NULL;
+ }
+
+ dspfd = open("/dev/dsp", O_WRONLY);
+ if (dspfd == -1) {
+ perror("open(\"/dev/dsp\")");
+ close(randfd);
+ return NULL;
+ }
+
+ frag = (2 << 16) | 13;
+ ret = ioctl(dspfd, SNDCTL_DSP_SETFRAGMENT, &frag);
+ if (ret < 0)
+ perror("SNDCTL_DSP_SETFRAGMENT");
+
+ stereo = 1; bits = 16; rate = 22050;
+ ret = ioctl(dspfd, SNDCTL_DSP_STEREO, &stereo);
+ if (ret == 0)
+ ret = ioctl(dspfd, SNDCTL_DSP_SETFMT, &bits);
+ if (ret == 0)
+ ret = ioctl(dspfd, SNDCTL_DSP_SPEED, &rate);
+ if (ret < 0)
+ perror("failed to set audio format");
+
+ while (1) {
+ pthread_mutex_lock(&snd_mutex);
+ if (!snd_test_l && !snd_test_r)
+ pthread_cond_wait(&snd_cond, &snd_mutex);
+ pthread_mutex_unlock(&snd_mutex);
+
+ if (snd_test_quit)
+ break;
+
+ ret = read(randfd, buf, sizeof(buf));
+ if (ret == -1) {
+ perror("urandom read");
+ break;
+ }
+
+ if (!snd_test_l)
+ for (i = 0; i < array_size(buf) / 2; i++)
+ buf[i * 2] = 0;
+ if (!snd_test_r)
+ for (i = 0; i < array_size(buf) / 2; i++)
+ buf[i * 2 + 1] = 0;
+
+ ret = write(dspfd, buf, sizeof(buf));
+ if (ret == -1) {
+ perror("dsp write");
+ break;
+ }
+ }
+
+ close(randfd);
+ close(dspfd);
+
+ return NULL;
+}
+
+static void sound_init(void)
+{
+ pthread_t tid;
+ int ret;
+
+ ret = pthread_create(&tid, NULL, sound_thread, NULL);
+ if (ret != 0) {
+ fprintf(stderr, "pthread_create sound_thread: %d\n", ret);
+ return;
+ }
+ pthread_detach(tid);
+}
+
+static void sound_do(int l, int r)
+{
+ pthread_mutex_lock(&snd_mutex);
+ snd_test_l = l;
+ snd_test_r = r;
+ if (l || r || snd_test_quit)
+ pthread_cond_signal(&snd_cond);
+ pthread_mutex_unlock(&snd_mutex);
+}
+