qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] Re: esd audio output patch and debuging.
@ 2006-09-04  0:07 malc
  2006-09-04  5:33 ` Frederick Reeve
  0 siblings, 1 reply; 10+ messages in thread
From: malc @ 2006-09-04  0:07 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 73 bytes --]


Attached patch fixes a couple of problems.

--
mailto:malc@pulsesoft.com

[-- Attachment #2: Type: TEXT/PLAIN, Size: 2505 bytes --]

Index: esdaudio.c
===================================================================
RCS file: /home/malc/cvsroot/bellard/qemu/audio/Attic/esdaudio.c,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 esdaudio.c
--- esdaudio.c	3 Sep 2006 21:57:19 -0000	1.1.2.1
+++ esdaudio.c	3 Sep 2006 23:58:29 -0000
@@ -1,7 +1,7 @@
 /*
  * QEMU ESD audio driver
  *
- * Copyright (c) 2006 Frederick Reeve (brushed up malc)
+ * Copyright (c) 2006 Frederick Reeve (brushed up by malc)
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -44,8 +44,10 @@
 
 static struct {
     int samples;
+    int divisor;
 } conf = {
-    1024
+    1024,
+    2
 };
 
 static void GCC_FMT_ATTR (2, 3) esd_logerr (int err, const char *fmt, ...)
@@ -117,22 +119,25 @@
 {
     ESDVoiceOut *esd = arg;
     HWVoiceOut *hw = &esd->hw;
+    int threshold;
+
+    threshold = conf.divisor ? hw->samples / conf.divisor : 0;
 
     for (;;) {
         int decr, to_mix, rpos;
 
-        if (esd->done) {
-            break;
-        }
-
-        if (esd_cwait (esd, AUDIO_FUNC)) {
+        for (;;) {
             if (esd->done) {
+                goto exit;
+            }
+
+            if (esd->live > threshold) {
                 break;
             }
-        }
 
-        if (esd->live < hw->samples / 2) {
-            continue;
+            if (esd_cwait (esd, AUDIO_FUNC)) {
+                goto exit;
+            }
         }
 
         decr = to_mix = esd->live;
@@ -176,14 +181,16 @@
             to_mix -= chunk;
         }
 
-        if (esd_mlock (esd, AUDIO_FUNC))
+        if (esd_mlock (esd, AUDIO_FUNC)) {
             return NULL;
+        }
 
         esd->rpos = rpos;
-        esd->live = 0;
+        esd->live -= decr;
         esd->decr += decr;
     }
 
+ exit:
     esd_munlock (esd, AUDIO_FUNC);
     return NULL;
 }
@@ -235,7 +242,7 @@
         goto fail1;
     }
 
-    esdfmt = as->nchannels == 2 ? ESD_STEREO : ESD_MONO;
+    esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
     switch (as->fmt) {
         case AUD_FMT_S8:
         case AUD_FMT_U8:
@@ -371,6 +378,9 @@
     {"SAMPLES", AUD_OPT_INT, &conf.samples,
      "buffer size in samples", NULL, 0},
 
+    {"DIVISOR", AUD_OPT_INT, &conf.divisor,
+     "threshold divisor", NULL, 0},
+
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 

^ permalink raw reply	[flat|nested] 10+ messages in thread
* [Qemu-devel] Re: esd audio output patch and debuging.
@ 2006-09-03 22:33 malc
  2006-09-04  8:56 ` Peter Oberndorfer
  0 siblings, 1 reply; 10+ messages in thread
From: malc @ 2006-09-03 22:33 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 935 bytes --]

Frederick Reeve <cylix <at> solace.info> writes:

> 
> Hello.
>

[..snip..]

> 
> Now, I would not have you thinking this patch is a ready to go.  I
> am writing this email because I am having a little trouble with
> this.  It outputs sound fine but it produces artafacts.  I'm not
> sure of the cause.  Though I think it may have to do with frame
> alignment or with the conversion process (see code).  It sounds like
> its clipping at high sample volume but this is the first time I have
> done anything with audio programing.  I had planed to submit a
> completed patch but...  anyway if anyone can point me in the right
> direction I would appreciate it.  Alternately if you just want to
> fix it that would be great to.

Implemented the ideas described in previous post, latency is no good
(something to be expected) but the quality seems to be fine now.

Fabrice: i think this can be safely applied.

--
mailto:malc@pulsesoft.com

[-- Attachment #2: Type: TEXT/PLAIN, Size: 15297 bytes --]

Index: Makefile.target
===================================================================
RCS file: /home/malc/cvsroot/bellard/qemu/Makefile.target,v
retrieving revision 1.1.1.10
retrieving revision 1.1.1.1.2.11
diff -u -r1.1.1.10 -r1.1.1.1.2.11
--- Makefile.target	4 Aug 2006 23:49:02 -0000	1.1.1.10
+++ Makefile.target	3 Sep 2006 21:56:08 -0000	1.1.1.1.2.11
@@ -315,6 +315,10 @@
 AUDIODRV += dsoundaudio.o
 LIBS += -lole32 -ldxguid
 endif
+ifdef CONFIG_ESD
+AUDIODRV += esdaudio.o
+LIBS += -lesd
+endif
 ifdef CONFIG_FMOD
 AUDIODRV += fmodaudio.o
 audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
@@ -539,7 +543,7 @@
 endif
 
 ifeq (1, 0)
-audio.o sdlaudio.o dsoundaudio.o ossaudio.o wavaudio.o noaudio.o \
+audio.o sdlaudio.o dsoundaudio.o ossaudio.o wavaudio.o noaudio.o esdaudio.o \
 fmodaudio.o alsaaudio.o mixeng.o sb16.o es1370.o gus.o adlib.o: \
 CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
 endif
Index: configure
===================================================================
RCS file: /home/malc/cvsroot/bellard/qemu/configure,v
retrieving revision 1.1.1.8
retrieving revision 1.1.1.1.2.6
diff -u -r1.1.1.8 -r1.1.1.1.2.6
--- configure	27 Jun 2006 11:05:10 -0000	1.1.1.8
+++ configure	3 Sep 2006 21:56:15 -0000	1.1.1.1.2.6
@@ -81,6 +81,7 @@
 dsound="no"
 coreaudio="no"
 alsa="no"
+esd="no"
 fmod="no"
 fmod_lib=""
 fmod_inc=""
@@ -207,6 +208,8 @@
   ;;
   --enable-dsound) dsound="yes"
   ;;
+  --enable-esd) esd="yes"
+  ;;
   --enable-fmod) fmod="yes"
   ;;
   --fmod-lib=*) fmod_lib="$optarg"
@@ -282,6 +285,7 @@
 echo "  --enable-adlib           enable Adlib emulation"
 echo "  --enable-coreaudio       enable Coreaudio audio driver"
 echo "  --enable-alsa            enable ALSA audio driver"
+echo "  --enable-esd             enable esd audio"
 echo "  --enable-fmod            enable FMOD audio driver"
 echo "  --enabled-dsound         enable DirectSound audio driver"
 echo "  --enable-system          enable all system emulation targets"
@@ -545,6 +549,7 @@
 echo "CoreAudio support $coreaudio"
 echo "ALSA support      $alsa"
 echo "DSound support    $dsound"
+echo "ESD support       $esd"
 if test "$fmod" = "yes"; then
     if test -z $fmod_lib || test -z $fmod_inc; then
         echo
@@ -694,6 +699,10 @@
   echo "CONFIG_DSOUND=yes" >> $config_mak
   echo "#define CONFIG_DSOUND 1" >> $config_h
 fi
+if test "$esd" = "yes" ; then
+  echo "CONFIG_ESD=yes" >> $config_mak
+  echo "#define CONFIG_ESD 1" >> $config_h
+fi
 if test "$fmod" = "yes" ; then
   echo "CONFIG_FMOD=yes" >> $config_mak
   echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak
Index: audio/audio.c
===================================================================
RCS file: /home/malc/cvsroot/bellard/qemu/audio/audio.c,v
retrieving revision 1.1.1.8
retrieving revision 1.1.1.1.2.20
diff -u -r1.1.1.8 -r1.1.1.1.2.20
--- audio/audio.c	4 Aug 2006 23:49:09 -0000	1.1.1.8
+++ audio/audio.c	3 Sep 2006 21:57:03 -0000	1.1.1.1.2.20
@@ -46,6 +46,9 @@
 #ifdef CONFIG_DSOUND
     &dsound_audio_driver,
 #endif
+#ifdef CONFIG_ESD
+    &esd_audio_driver,
+#endif
 #ifdef CONFIG_FMOD
     &fmod_audio_driver,
 #endif
@@ -605,11 +608,11 @@
     }
 
     if (info->sign) {
-        memset (buf, 0x00, len << info->shift);
+        memset (buf, len << info->shift, 0x00);
     }
     else {
         if (info->bits == 8) {
-            memset (buf, 0x80, len << info->shift);
+            memset (buf, len << info->shift, 0x80);
         }
         else {
             int i;
Index: audio/audio_int.h
===================================================================
RCS file: /home/malc/cvsroot/bellard/qemu/audio/audio_int.h,v
retrieving revision 1.1.1.7
retrieving revision 1.1.1.1.2.7
diff -u -r1.1.1.7 -r1.1.1.1.2.7
--- audio/audio_int.h	4 Aug 2006 23:49:09 -0000	1.1.1.7
+++ audio/audio_int.h	3 Sep 2006 21:57:09 -0000	1.1.1.1.2.7
@@ -200,6 +200,7 @@
 extern struct audio_driver wav_audio_driver;
 extern struct audio_driver fmod_audio_driver;
 extern struct audio_driver alsa_audio_driver;
+extern struct audio_driver esd_audio_driver;
 extern struct audio_driver coreaudio_audio_driver;
 extern struct audio_driver dsound_audio_driver;
 extern volume_t nominal_volume;
Index: audio/esdaudio.c
===================================================================
RCS file: audio/esdaudio.c
diff -N audio/esdaudio.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ audio/esdaudio.c	3 Sep 2006 21:57:19 -0000	1.1.2.1
@@ -0,0 +1,404 @@
+/*
+ * QEMU ESD audio driver
+ *
+ * Copyright (c) 2006 Frederick Reeve (brushed up malc)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <esd.h>
+#include <pthread.h>
+
+#include "vl.h"
+
+#define AUDIO_CAP "esd"
+#include "audio_int.h"
+
+typedef struct ESDVoiceOut {
+    HWVoiceOut hw;
+    int done;
+    int live;
+    int decr;
+    int rpos;
+    void *pcm_buf;
+    int fd;
+    pthread_t thread;
+    pthread_cond_t cond;
+    pthread_mutex_t mutex;
+} ESDVoiceOut;
+
+static struct {
+    int samples;
+} conf = {
+    1024
+};
+
+static void GCC_FMT_ATTR (2, 3) esd_logerr (int err, const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start (ap, fmt);
+    AUD_vlog (AUDIO_CAP, fmt, ap);
+    va_end (ap);
+
+    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
+}
+
+static int esd_mlock (ESDVoiceOut *esd, const char *caller)
+{
+    int err;
+
+    err = pthread_mutex_lock (&esd->mutex);
+    if (err) {
+        esd_logerr (err, "pthread_mutex_lock failed for %s", caller);
+        return -1;
+    }
+    return 0;
+}
+
+static int esd_munlock (ESDVoiceOut *esd, const char *caller)
+{
+    int err;
+
+    err = pthread_mutex_unlock (&esd->mutex);
+    if (err) {
+        esd_logerr (err, "pthread_mutex_unlock failed for %s", caller);
+        return -1;
+    }
+    return 0;
+}
+
+static int esd_cwait (ESDVoiceOut *esd, const char *caller)
+{
+    int err;
+
+    err = pthread_cond_wait (&esd->cond, &esd->mutex);
+    if (err) {
+        esd_logerr (err, "pthread_cond_wait failed for %s", caller);
+        return -1;
+    }
+    return 0;
+}
+
+static int esd_munlock_and_csignal (ESDVoiceOut *esd, const char *caller)
+{
+    int err;
+
+    err = pthread_mutex_unlock (&esd->mutex);
+    if (err) {
+        esd_logerr (err, "[us] pthread_mutex_unlock failed for %s", caller);
+        return -1;
+    }
+
+    err = pthread_cond_signal (&esd->cond);
+    if (err) {
+        esd_logerr (err, "[us] pthread_cond_signal failed for %s", caller);
+        return -1;
+    }
+    return 0;
+}
+
+static void *esd_thread (void *arg)
+{
+    ESDVoiceOut *esd = arg;
+    HWVoiceOut *hw = &esd->hw;
+
+    for (;;) {
+        int decr, to_mix, rpos;
+
+        if (esd->done) {
+            break;
+        }
+
+        if (esd_cwait (esd, AUDIO_FUNC)) {
+            if (esd->done) {
+                break;
+            }
+        }
+
+        if (esd->live < hw->samples / 2) {
+            continue;
+        }
+
+        decr = to_mix = esd->live;
+        rpos = hw->rpos;
+
+        if (esd_munlock (esd, AUDIO_FUNC)) {
+            return NULL;
+        }
+
+        while (to_mix) {
+            ssize_t written;
+            int chunk = audio_MIN (to_mix, hw->samples - rpos);
+            st_sample_t *src = hw->mix_buf + rpos;
+
+            hw->clip (esd->pcm_buf, src, chunk);
+
+        again:
+            written = write (esd->fd, esd->pcm_buf, chunk << hw->info.shift);
+            if (written == -1) {
+                if (errno == EINTR || errno == EAGAIN) {
+                    goto again;
+                }
+                esd_logerr (errno, "write failed");
+                return NULL;
+            }
+
+            if (written != chunk << hw->info.shift) {
+                int wsamples = written >> hw->info.shift;
+                int wbytes = wsamples << hw->info.shift;
+                if (wbytes != written) {
+                    dolog ("warning: Misaligned write %d (requested %d), "
+                           "alignment %d\n",
+                           wbytes, written, hw->info.align + 1);
+                }
+                to_mix -= wsamples;
+                rpos = (rpos + wsamples) % hw->samples;
+                break;
+            }
+
+            rpos = (rpos + chunk) % hw->samples;
+            to_mix -= chunk;
+        }
+
+        if (esd_mlock (esd, AUDIO_FUNC))
+            return NULL;
+
+        esd->rpos = rpos;
+        esd->live = 0;
+        esd->decr += decr;
+    }
+
+    esd_munlock (esd, AUDIO_FUNC);
+    return NULL;
+}
+
+static int esd_run_out (HWVoiceOut *hw)
+{
+    int live, decr;
+    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
+
+    if (esd_mlock (esd, AUDIO_FUNC)) {
+        return 0;
+    }
+
+    live = audio_pcm_hw_get_live_out (hw);
+    decr = audio_MIN (live, esd->decr);
+    esd->decr -= decr;
+    esd->live = live - decr;
+    hw->rpos = esd->rpos;
+    if (esd->live > 0) {
+        esd_munlock_and_csignal (esd, AUDIO_FUNC);
+    }
+    else {
+        esd_munlock (esd, AUDIO_FUNC);
+    }
+    return decr;
+}
+
+static int esd_write_out (SWVoiceOut *sw, void *buf, int len)
+{
+    return audio_pcm_sw_write (sw, buf, len);
+}
+
+static int esd_init_out (HWVoiceOut *hw, audsettings_t *as)
+{
+    int i, err;
+    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
+    audsettings_t obt_as = *as;
+    int esdfmt = ESD_STREAM | ESD_PLAY;
+
+    err = pthread_mutex_init (&esd->mutex, NULL);
+    if (err) {
+        esd_logerr (err, "%s: pthread_mutex_init failed", AUDIO_FUNC);
+        goto fail0;
+    }
+
+    err = pthread_cond_init (&esd->cond, NULL);
+    if (err) {
+        esd_logerr (err, "%s: pthread_cond_init failed", AUDIO_FUNC);
+        goto fail1;
+    }
+
+    esdfmt = as->nchannels == 2 ? ESD_STEREO : ESD_MONO;
+    switch (as->fmt) {
+        case AUD_FMT_S8:
+        case AUD_FMT_U8:
+            esdfmt |= ESD_BITS8;
+            obt_as.fmt = AUD_FMT_U8;
+            break;
+
+        case AUD_FMT_S16:
+        case AUD_FMT_U16:
+            esdfmt |= ESD_BITS16;
+            obt_as.fmt = AUD_FMT_S16;
+            break;
+    }
+    obt_as.endianness = 0;
+
+    audio_pcm_init_info (&hw->info, &obt_as);
+
+    hw->samples = conf.samples;
+    esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+    if (!esd->pcm_buf) {
+        dolog ("Could not allocate buffer (%d bytes)\n",
+               hw->samples << hw->info.shift);
+        return -1;
+    }
+
+    esd->fd = -1;
+    for (i = 0; i < 10000; i++) {
+        esd->fd = esd_play_stream (esdfmt, as->freq, NULL, NULL);
+        if (esd->fd < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            esd_logerr (errno, "esd_play_stream failed");
+            goto fail2;
+        }
+        break;
+    }
+
+    if (esd->fd < 0) {
+        esd_logerr (errno, "esd_play_stream failed");
+        goto fail2;
+    }
+
+    err = pthread_create (&esd->thread, NULL, esd_thread, esd);
+    if (err) {
+        esd_logerr (err, "%s: pthred_create failed", AUDIO_FUNC);
+        goto fail3;
+    }
+
+    return 0;
+
+ fail3:
+    if (close (esd->fd)) {
+        esd_logerr (errno, "%s: close on esd socket(%d) failed",
+                    AUDIO_FUNC, esd->fd);
+    }
+    esd->fd = -1;
+
+ fail2:
+    qemu_free (esd->pcm_buf);
+    esd->pcm_buf = NULL;
+
+    err = pthread_cond_destroy (&esd->cond);
+    if (err) {
+        esd_logerr (err, "%s: pthread_cond_destroy failed", AUDIO_FUNC);
+    }
+
+ fail1:
+    err = pthread_mutex_destroy (&esd->mutex);
+    if (err) {
+        esd_logerr (err, "%s: pthread_mutex_destroy failed", AUDIO_FUNC);
+    }
+
+ fail0:
+    return -1;
+}
+
+static void esd_fini_out (HWVoiceOut *hw)
+{
+    int err;
+    void *ret;
+    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
+
+    esd_mlock (esd, AUDIO_FUNC);
+    esd->done = 1;
+    esd_munlock_and_csignal (esd, AUDIO_FUNC);
+
+    err = pthread_join (esd->thread, &ret);
+    if (err) {
+        esd_logerr (err, "%s: pthread_join failed", AUDIO_FUNC);
+    }
+
+    if (esd->fd >= 0) {
+        if (close (esd->fd)) {
+            esd_logerr (errno, "failed to close esd socket");
+        }
+        esd->fd = -1;
+    }
+
+    err = pthread_cond_destroy (&esd->cond);
+    if (err) {
+        esd_logerr (err, "%s: pthread_cond_destroy failed", AUDIO_FUNC);
+    }
+
+    err = pthread_mutex_destroy (&esd->mutex);
+    if (err) {
+        esd_logerr (err, "%s: pthread_mutex_destroy failed", AUDIO_FUNC);
+    }
+
+    qemu_free (esd->pcm_buf);
+    esd->pcm_buf = NULL;
+}
+
+static int esd_ctl_out (HWVoiceOut *hw, int cmd, ...)
+{
+    (void) hw;
+    (void) cmd;
+    return 0;
+}
+
+static void *esd_audio_init (void)
+{
+    return &conf;
+}
+
+static void esd_audio_fini (void *opaque)
+{
+    (void) opaque;
+    ldebug ("esd_fini");
+}
+
+struct audio_option esd_options[] = {
+    {"SAMPLES", AUD_OPT_INT, &conf.samples,
+     "buffer size in samples", NULL, 0},
+
+    {NULL, 0, NULL, NULL, NULL, 0}
+};
+
+struct audio_pcm_ops esd_pcm_ops = {
+    esd_init_out,
+    esd_fini_out,
+    esd_run_out,
+    esd_write_out,
+    esd_ctl_out,
+
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+struct audio_driver esd_audio_driver = {
+    INIT_FIELD (name           = ) "esd",
+    INIT_FIELD (descr          = )
+    "http://en.wikipedia.org/wiki/Esound",
+    INIT_FIELD (options        = ) esd_options,
+    INIT_FIELD (init           = ) esd_audio_init,
+    INIT_FIELD (fini           = ) esd_audio_fini,
+    INIT_FIELD (pcm_ops        = ) &esd_pcm_ops,
+    INIT_FIELD (can_be_default = ) 0,
+    INIT_FIELD (max_voices_out = ) 1,
+    INIT_FIELD (max_voices_in  = ) 0,
+    INIT_FIELD (voice_size_out = ) sizeof (ESDVoiceOut),
+    INIT_FIELD (voice_size_in  = ) 0
+};

^ permalink raw reply	[flat|nested] 10+ messages in thread
* [Qemu-devel] esd audio output patch and debuging.
@ 2006-08-30 15:45 Frederick Reeve
  2006-08-31 11:46 ` [Qemu-devel] " malc
  0 siblings, 1 reply; 10+ messages in thread
From: Frederick Reeve @ 2006-08-30 15:45 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 3139 bytes --]

Hello.

Attached you will find a patch for esd audio support in QEMU.  It is more or less a large modification of audio/wavaudio.c. The patch will apply against the latest tarball release http://fabrice.bellard.free.fr/qemu/qemu-0.8.2.tar.gz (0.8.2 at the time of this writing).  You will of course need libesd to compile this.  To apply and test on linux/*nix simply:

$ cd qemu-src-dir
$ patch -Np1 -i path/to/patch/file
$ ./configure --enable-esd
$ make
$ sudo make install
$ export QEMU_AUDIO_DRV=esd
$ qemu (your options here) -soundhw es1370

You will also need to make sure esd is running when you do that of course.  Sorry if that is insulting your intelegence.  I just wanted to make everything very clear.

Now, I would not have you thinking this patch is a ready to go.  I am writing this email because I am having a little trouble with this.  It outputs sound fine but it produces artafacts.  I'm not sure of the cause.  Though I think it may have to do with frame alignment or with the conversion process (see code).  It sounds like its clipping at high sample volume but this is the first time I have done anything with audio programing.  I had planed to submit a completed patch but...  anyway if anyone can point me in the right direction I would appreciate it.  Alternately if you just want to fix it that would be great to. :-)

Just a note also on esd as far as I can tell it only supports 8 and 16 bit unsigned.

You may be wondering why with all the sound support options qemu has that I would want to write another one.  Here is the logic.  I am running an LTSP server setup.  The servers I use have no sound card at all.  Yet all the programs run on that server.  The clients however have sound cards.  None of QEMUs sound outputs will work without a sound card with the exeption of wav.  None of QEMUs sound outputs can be broadcast over a network to clients but esd can.  In short esd support allows me to run many QEMU copies on a server and output the audio to client terminals with out the server even having a sound card.  esd is old but its about the only well supported option for network audio output in both linux distros and LTSP.

Background:  I am maintaining LTSP servers for small elementy schools with "no budget".  I currently maintain these networks for free to help with education though they may be offering me a job in the future.  The teachers require a small few windows programs that do not run under wine.  So I pipe qemu over the thin terms and use gdm so when they log into a qemu session it just pulls up windows full screen.  Howerver they have resently needed sound and yes they actualy need it (though I whish I could say they didn't).  School will be starting on september 4 and I am trying to be ready.

Anyway if you have any questions or I can help at all let me know.
If you can see what is wrong or have sugestions I welcome help.  Also if you know of a better way that I would be happy to here it but after looking at our situation I think this sound module is the path of least resistance.

I thank you also for QEMU it has been a huge boon to the schools.

Thanks

Frederick


[-- Attachment #2: qemu-0.8.2-esd.patch --]
[-- Type: application/octet-stream, Size: 9725 bytes --]

diff -Nru qemu-0.8.2/audio/audio.c qemu-0.8.2.new/audio/audio.c
--- qemu-0.8.2/audio/audio.c	2006-07-22 12:23:34.000000000 -0500
+++ qemu-0.8.2.new/audio/audio.c	2006-08-29 21:42:17.000000000 -0500
@@ -46,6 +46,9 @@
 #ifdef CONFIG_DSOUND
     &dsound_audio_driver,
 #endif
+#ifdef CONFIG_ESD
+    &esd_audio_driver,
+#endif
 #ifdef CONFIG_FMOD
     &fmod_audio_driver,
 #endif
diff -Nru qemu-0.8.2/audio/audio_int.h qemu-0.8.2.new/audio/audio_int.h
--- qemu-0.8.2/audio/audio_int.h	2006-07-22 12:23:34.000000000 -0500
+++ qemu-0.8.2.new/audio/audio_int.h	2006-08-29 21:27:31.000000000 -0500
@@ -200,6 +200,7 @@
 extern struct audio_driver wav_audio_driver;
 extern struct audio_driver fmod_audio_driver;
 extern struct audio_driver alsa_audio_driver;
+extern struct audio_driver esd_audio_driver;
 extern struct audio_driver coreaudio_audio_driver;
 extern struct audio_driver dsound_audio_driver;
 extern volume_t nominal_volume;
diff -Nru qemu-0.8.2/audio/esdaudio.c qemu-0.8.2.new/audio/esdaudio.c
--- qemu-0.8.2/audio/esdaudio.c	1969-12-31 18:00:00.000000000 -0600
+++ qemu-0.8.2.new/audio/esdaudio.c	2006-08-29 23:20:56.000000000 -0500
@@ -0,0 +1,235 @@
+/*
+ * QEMU ESD audio driver
+ *
+ * Copyright (c) 2006 Vassili Karpov (malc) + Frederick Reeve
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#define AUDIO_CAP "esd"
+
+#include "audio_int.h"
+#include <stdio.h>
+#include <esd.h>
+
+typedef struct ESDVoiceOut {
+    HWVoiceOut hw;
+    int64_t old_ticks;
+    void *pcm_buf;
+} ESDVoiceOut;
+
+static struct {
+    audsettings_t settings;
+	int esd__out_sock;
+	int esd__out_channels;
+	int esd__out_bits;
+	int esd__out_rate;
+	int esd__out_mode;
+	int esd__out_func;
+	esd_format_t esd__out_format;
+} conf = {
+    {
+        44100,
+        1,
+        AUD_FMT_U8
+    },
+    0,
+	ESD_MONO,
+	ESD_BITS8,
+	44100,
+	ESD_STREAM,
+	ESD_PLAY,
+	0
+};
+
+static int esd_run_out (HWVoiceOut *hw)
+{
+    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
+    int rpos, live, decr, samples;
+    uint8_t *dst;
+    st_sample_t *src;
+    int64_t now = qemu_get_clock (vm_clock);
+    int64_t ticks = now - esd->old_ticks;
+    int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
+
+    if (bytes > INT_MAX) {
+        samples = INT_MAX >> hw->info.shift;
+    }
+    else {
+        samples = bytes >> hw->info.shift;
+    }
+
+    live = audio_pcm_hw_get_live_out (hw);
+    if (!live) {
+        return 0;
+    }
+
+    esd->old_ticks = now;
+    decr = audio_MIN (live, samples);
+    samples = decr;
+    rpos = hw->rpos;
+    while (samples) {
+        int left_till_end_samples = hw->samples - rpos;
+        int convert_samples = audio_MIN (samples, left_till_end_samples);
+
+        src = hw->mix_buf + rpos;
+        dst = advance (esd->pcm_buf, rpos << hw->info.shift);
+
+        hw->clip (dst, src, convert_samples);
+		
+		write (conf.esd__out_sock, dst, convert_samples << hw->info.shift);
+		
+        rpos = (rpos + convert_samples) % hw->samples;
+        samples -= convert_samples;
+    }
+
+    hw->rpos = rpos;
+    return decr;
+}
+
+static int esd_write_out (SWVoiceOut *sw, void *buf, int len)
+{
+    return audio_pcm_sw_write (sw, buf, len);
+}
+
+static int esd_init_out (HWVoiceOut *hw, audsettings_t *as)
+{
+	ESDVoiceOut *esd = (ESDVoiceOut *) hw;
+    audsettings_t esd__as = conf.settings;
+
+    (void) as;
+
+    conf.esd__out_channels = (esd__as.nchannels == 2) ? ESD_STEREO : ESD_MONO;
+	
+	/* ###fix-me### should through an error if we get a signed type */
+    switch (esd__as.fmt) {
+	case AUD_FMT_S8:
+    case AUD_FMT_U8:
+        conf.esd__out_bits = ESD_BITS8;
+/*		conf.esd__bytes_per_frame = esd__as.nchannels; */
+        break;
+
+    case AUD_FMT_S16:
+    case AUD_FMT_U16:
+		conf.esd__out_bits = ESD_BITS16;
+/*		conf.esd__bytes_per_frame = (esd__as.nchannels * 2); */
+        break;
+    }
+
+	conf.esd__out_format = conf.esd__out_bits | conf.esd__out_channels | conf.esd__out_mode | conf.esd__out_func;
+	conf.esd__out_rate = (int) conf.settings.freq;
+    esd__as.endianness = 0;
+    audio_pcm_init_info (&hw->info, &esd__as);
+
+	
+    hw->samples = 2048;  /* 1024 */
+    esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+    if (!esd->pcm_buf) {
+        dolog ("Could not allocate buffer (%d bytes)\n",
+               hw->samples << hw->info.shift);
+        return -1;
+    }
+	
+	conf.esd__out_sock = esd_play_stream (conf.esd__out_format, conf.esd__out_rate, NULL, (char *) NULL);
+	
+    if (!conf.esd__out_sock) {
+		/* Failed to open esd socket */
+        qemu_free (esd->pcm_buf);
+        esd->pcm_buf = NULL;
+        return -1;
+    }
+
+    return 0;
+}
+
+static void esd_fini_out (HWVoiceOut *hw)
+{
+    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
+
+    if (!conf.esd__out_sock) {
+        return;
+    }
+
+    close (conf.esd__out_sock);
+    conf.esd__out_sock = 0;
+
+    qemu_free (esd->pcm_buf);
+    esd->pcm_buf = NULL;
+}
+
+static int esd_ctl_out (HWVoiceOut *hw, int cmd, ...)
+{
+    (void) hw;
+    (void) cmd;
+    return 0;
+}
+
+static void *esd_audio_init (void)
+{
+    return &conf;
+}
+
+static void esd_audio_fini (void *opaque)
+{
+    (void) opaque;
+    ldebug ("esd_fini");
+}
+
+struct audio_option esd_options[] = {
+    {"FREQUENCY", AUD_OPT_INT, &conf.settings.freq,
+     "Frequency", NULL, 0},
+
+/*    {"FORMAT", AUD_OPT_FMT, &conf.settings.fmt,
+     "Format", NULL, 0}, */
+
+    {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.settings.nchannels,
+     "Number of channels (1 - mono, 2 - stereo)", NULL, 0},
+
+    {NULL, 0, NULL, NULL, NULL, 0}
+};
+
+struct audio_pcm_ops esd_pcm_ops = {
+    esd_init_out,
+    esd_fini_out,
+    esd_run_out,
+    esd_write_out,
+    esd_ctl_out,
+
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+struct audio_driver esd_audio_driver = {
+    INIT_FIELD (name           = ) "esd",
+    INIT_FIELD (descr          = )
+    "esd networked audio mixing",
+    INIT_FIELD (options        = ) esd_options,
+    INIT_FIELD (init           = ) esd_audio_init,
+    INIT_FIELD (fini           = ) esd_audio_fini,
+    INIT_FIELD (pcm_ops        = ) &esd_pcm_ops,
+    INIT_FIELD (can_be_default = ) 0,
+    INIT_FIELD (max_voices_out = ) 1,
+    INIT_FIELD (max_voices_in  = ) 0,
+    INIT_FIELD (voice_size_out = ) sizeof (ESDVoiceOut),
+    INIT_FIELD (voice_size_in  = ) 0
+};
diff -Nru qemu-0.8.2/configure qemu-0.8.2.new/configure
--- qemu-0.8.2/configure	2006-07-22 12:23:34.000000000 -0500
+++ qemu-0.8.2.new/configure	2006-08-29 20:52:21.000000000 -0500
@@ -81,6 +81,7 @@
 dsound="no"
 coreaudio="no"
 alsa="no"
+esd="no"
 fmod="no"
 fmod_lib=""
 fmod_inc=""
@@ -207,6 +208,8 @@
   ;;
   --enable-dsound) dsound="yes"
   ;;
+  --enable-esd) esd="yes"
+  ;;
   --enable-fmod) fmod="yes"
   ;;
   --fmod-lib=*) fmod_lib="$optarg"
@@ -282,6 +285,7 @@
 echo "  --enable-adlib           enable Adlib emulation"
 echo "  --enable-coreaudio       enable Coreaudio audio driver"
 echo "  --enable-alsa            enable ALSA audio driver"
+echo "  --enable-esd             enable esd audio"
 echo "  --enable-fmod            enable FMOD audio driver"
 echo "  --enabled-dsound         enable DirectSound audio driver"
 echo "  --enable-system          enable all system emulation targets"
@@ -545,6 +549,7 @@
 echo "CoreAudio support $coreaudio"
 echo "ALSA support      $alsa"
 echo "DSound support    $dsound"
+echo "ESD support       $esd"
 if test "$fmod" = "yes"; then
     if test -z $fmod_lib || test -z $fmod_inc; then
         echo
@@ -694,6 +699,10 @@
   echo "CONFIG_DSOUND=yes" >> $config_mak
   echo "#define CONFIG_DSOUND 1" >> $config_h
 fi
+if test "$esd" = "yes" ; then
+  echo "CONFIG_ESD=yes" >> $config_mak
+  echo "#define CONFIG_ESD 1" >> $config_h
+fi
 if test "$fmod" = "yes" ; then
   echo "CONFIG_FMOD=yes" >> $config_mak
   echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak
diff -Nru qemu-0.8.2/Makefile.target qemu-0.8.2.new/Makefile.target
--- qemu-0.8.2/Makefile.target	2006-07-22 12:23:34.000000000 -0500
+++ qemu-0.8.2.new/Makefile.target	2006-08-29 21:06:08.000000000 -0500
@@ -314,6 +314,10 @@
 AUDIODRV += dsoundaudio.o
 LIBS += -lole32 -ldxguid
 endif
+ifdef CONFIG_ESD
+AUDIODRV += esdaudio.o
+LIBS += -lesd
+endif
 ifdef CONFIG_FMOD
 AUDIODRV += fmodaudio.o
 audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
@@ -539,6 +543,6 @@
 
 ifeq (1, 0)
 audio.o sdlaudio.o dsoundaudio.o ossaudio.o wavaudio.o noaudio.o \
-fmodaudio.o alsaaudio.o mixeng.o sb16.o es1370.o gus.o adlib.o: \
+fmodaudio.o alsaaudio.o esdaudio.o mixeng.o sb16.o es1370.o gus.o adlib.o: \
 CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
 endif

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2006-09-04 13:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-04  0:07 [Qemu-devel] Re: esd audio output patch and debuging malc
2006-09-04  5:33 ` Frederick Reeve
  -- strict thread matches above, loose matches on Subject: below --
2006-09-03 22:33 malc
2006-09-04  8:56 ` Peter Oberndorfer
2006-09-04 12:01   ` Christophe Fillot
2006-09-04 14:04     ` Peter Oberndorfer
2006-09-04 12:02   ` malc
2006-08-30 15:45 [Qemu-devel] " Frederick Reeve
2006-08-31 11:46 ` [Qemu-devel] " malc
2006-08-31 17:19   ` Leonardo E. Reiter
2006-09-01 19:02     ` malc

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).