From: "Jim C. Brown" <jma5@umd.edu>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] arts output driver
Date: Sun, 10 Jul 2005 22:39:55 -0400 [thread overview]
Message-ID: <20050711023955.GA31186@jbrown.mylinuxbox.org> (raw)
[-- Attachment #1: Type: text/plain, Size: 376 bytes --]
Attached is a patch to add arts support to qemu, plus the actual driver.
Apply the patch and place artsaudio.c in the qemu/audio directory, and
reconfigure with the --enable-arts option.
artsaudio.c is derived from ossaudio.c and artsdsp.c (from the source code of
arts 1.3.2).
--
Infinite complexity begets infinite beauty.
Infinite precision begets infinite perfection.
[-- Attachment #2: arts.patch --]
[-- Type: text/plain, Size: 3128 bytes --]
--- qemu/audio/audio_int.h Sun Jul 10 22:21:02 2005
+++ qemu/audio/audio_int.h Wed Jun 1 00:08:36 2005
@@ -58,6 +58,9 @@
extern struct pcm_ops no_pcm_ops;
extern struct audio_output_driver no_output_driver;
+extern struct pcm_ops arts_pcm_ops;
+extern struct audio_output_driver arts_output_driver;
+
extern struct pcm_ops oss_pcm_ops;
extern struct audio_output_driver oss_output_driver;
--- qemu/audio/audio.c Sun Jul 10 22:21:27 2005
+++ qemu/audio/audio.c Wed Jun 1 00:08:05 2005
@@ -776,6 +776,9 @@
}
static struct audio_output_driver *drvtab[] = {
+#ifdef CONFIG_ARTS
+ &arts_output_driver,
+#endif
#ifdef CONFIG_OSS
&oss_output_driver,
#endif
--- qemu/Makefile.target Sun Jul 10 22:25:58 2005
+++ qemu/Makefile.target Wed Jul 6 23:40:55 2005
@@ -324,6 +324,10 @@
ifdef CONFIG_OSS
AUDIODRV += ossaudio.o
endif
+ifdef CONFIG_ARTS
+AUDIODRV += artsaudio.o
+LIBS += $(CONFIG_ARTS_LIB)
+endif
pc.o: DEFINES := -DUSE_SB16 $(DEFINES)
@@ -412,6 +416,9 @@
sdlaudio.o: sdlaudio.c
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
+
+artsaudio.o: artsaudio.c
+ $(CC) $(CFLAGS) $(DEFINES) $(CONFIG_ARTS_INC) -c -o $@ $<
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
--- qemu/configure Sun Jul 10 22:29:03 2005
+++ qemu/configure Sun Jun 12 17:44:24 2005
@@ -77,6 +77,9 @@
gdbstub="yes"
slirp="yes"
adlib="no"
+arts="no"
+arts_lib=""
+arts_inc=""
oss="no"
fmod="no"
fmod_lib=""
@@ -186,6 +189,12 @@
;;
--disable-slirp) slirp="no"
;;
+ --enable-arts) arts="yes"
+ ;;
+ --arts-lib=*) arts_lib=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --arts-inc=*) arts_inc=`echo $opt | cut -d '=' -f 2`
+ ;;
--enable-adlib) adlib="yes"
;;
--disable-kqemu) kqemu="no"
@@ -273,6 +282,40 @@
have_gcc3_options="yes"
fi
+if [ "$arts" = "yes" ]; then
+
+#dont bother with artsc-config check if both are given
+if [ "$arts_lib" = "" -o "$arts_inc" = "" ]; then
+
+if which artsc-config > /dev/null ; then
+
+if test -z "$arts_lib"; then
+
+arts_lib=`artsc-config --libs`
+
+fi
+
+if test -z "$arts_inc"; then
+
+arts_inc=`artsc-config --cflags`
+
+else
+
+arts_inc="-I$arts_inc"
+
+fi
+
+else
+
+ echo "artsc-config not found. Specify library and include dir manually."
+ arts="no"
+
+fi # artsc-config
+
+fi
+
+fi # arts
+
##########################################
# SDL probe
@@ -512,6 +555,11 @@
echo -n " (lib='$fmod_lib' include='$fmod_inc')"
fi
echo ""
+echo -n "Arts support $arts"
+if test $arts = "yes"; then
+ echo -n " (lib='$arts_lib' include='$arts_inc')"
+fi
+echo ""
echo "kqemu $kqemu"
echo "qvm86 $qvm86"
if test $kernel_module = "yes" -a $linux = "yes"; then
@@ -636,6 +684,12 @@
if test "$oss" = "yes" ; then
echo "CONFIG_OSS=yes" >> $config_mak
echo "#define CONFIG_OSS 1" >> $config_h
+fi
+if test "$arts" = "yes" ; then
+ echo "CONFIG_ARTS=yes" >> $config_mak
+ echo "CONFIG_ARTS_LIB=$arts_lib" >> $config_mak
+ echo "CONFIG_ARTS_INC=$arts_inc" >> $config_mak
+ echo "#define CONFIG_ARTS 1" >> $config_h
fi
if test "$fmod" = "yes" ; then
echo "CONFIG_FMOD=yes" >> $config_mak
[-- Attachment #3: artsaudio.c --]
[-- Type: text/plain, Size: 7755 bytes --]
/*
* QEMU Arts audio output driver
*
* Copyright (c) 2005 Jim Brown
*
* 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 <sys/types.h>
#include <sys/soundcard.h>
#include <assert.h>
#include <artsc.h>
#include "vl.h"
#include "audio/audio_int.h"
typedef struct ArtsVoice {
HWVoice hw;
void *pcm_buf;
arts_stream_t stream;
int nfrags;
int fragsize;
int stream_inited;
int old_optr;
int paused;
} ArtsVoice;
#define dolog(...) AUD_log ("arts", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
#define QC_ARTS_FRAGSIZE "QEMU_ARTS_FRAGSIZE"
#define QC_ARTS_NFRAGS "QEMU_ARTS_NFRAGS"
static struct {
int nfrags;
int fragsize;
} conf = {
.nfrags = 4,
.fragsize = 4096,
};
struct arts_params {
int freq;
audfmt_e fmt;
int nchannels;
int nfrags;
int fragsize;
};
static int arts_hw_write (SWVoice *sw, void *buf, int len)
{
return pcm_hw_write(sw, buf, len);
}
static int AUD_to_artsfmt (audfmt_e fmt)
{
switch (fmt) {
case AUD_FMT_S8: return -8;
case AUD_FMT_U8: return 8;
case AUD_FMT_S16: return -16;
case AUD_FMT_U16: return 16;
default:
dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
exit (EXIT_FAILURE);
}
}
static int arts_to_audfmt (int fmt)
{
switch (fmt) {
case -8: return AUD_FMT_S8;
case 8: return AUD_FMT_U8;
case -16: return AUD_FMT_S16;
case 16: return AUD_FMT_U16;
default:
dolog ("Internal logic error: Unrecognized Arts audio format %d\n"
"Aborting\n",
fmt);
exit (EXIT_FAILURE);
}
}
static int arts_open (struct arts_params *req, struct arts_params *obt, arts_stream_t *pstream)
{
arts_stream_t stream;
int fmt;
/* TODO: support signed vs unsigned data */
fmt = req->fmt;
if (fmt < 0)
fmt = -fmt;
stream = arts_play_stream(req->freq, fmt, req->nchannels, "qemu-arts");
arts_stream_set(stream, ARTS_P_BLOCKING, 1);
int mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
int fragSize = (mmmmssss & 0x7fff);
int fragCount = (mmmmssss & 0x7fff0000) >> 16;
if(fragSize > 1 && fragSize < 16)
{
if(fragCount < 2 || fragCount > 8192 || (fragCount * (1 << fragSize)) > 128*1024)
{
mmmmssss = 0x00030000+fragSize;
}
arts_stream_set(stream,ARTS_P_PACKET_SETTINGS,mmmmssss);
}
obt->nfrags = arts_stream_get(stream, ARTS_P_PACKET_COUNT);
obt->fragsize = arts_stream_get(stream, ARTS_P_PACKET_SIZE);
obt->freq = req->freq;
obt->fmt = req->fmt;
obt->nchannels = req->nchannels;
*pstream = stream;
if ((req->fmt != obt->fmt) ||
(req->nchannels != obt->nchannels) ||
(req->freq != obt->freq) ||
(req->fragsize != obt->fragsize) ||
(req->nfrags != obt->nfrags)) {
/* error - mismatch */
}
return 0;
}
static void arts_hw_run (HWVoice *hw)
{
ArtsVoice *arts = (ArtsVoice *) hw;
int rpos, live, decr;
int samples;
uint8_t *dst;
st_sample_t *src;
int written=0;
int bytes = 0;
live = pcm_hw_get_live (hw);
if ((live <= 0) || arts->paused)
return;
bytes = arts_stream_get(arts->stream, ARTS_P_BUFFER_SPACE);
decr = audio_MIN(bytes >> hw->shift, live);
if (decr <= 0) return;
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 = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
dst = advance (arts->pcm_buf, rpos << hw->shift);
hw->clip (dst, src, convert_samples);
written = arts_write (arts->stream, dst, convert_samples << hw->shift);
if (written < 0) {
dolog ("Failed to write audio\nReason: %d\n", written);
continue;
}
if (written != convert_samples << hw->shift) {
int wsamples = written >> hw->shift;
int wbytes = wsamples << hw->shift;
if (wbytes != written) {
dolog ("Unaligned write %d, %d\n", wbytes, written);
}
memset (src, 0, wbytes);
decr -= samples;
rpos = (rpos + wsamples) % hw->samples;
break;
}
memset (src, 0, convert_samples * sizeof (st_sample_t));
rpos = (rpos + convert_samples) % hw->samples;
samples -= convert_samples;
}
pcm_hw_dec_live (hw, decr);
hw->rpos = rpos;
}
static void arts_hw_fini (HWVoice *hw)
{
ArtsVoice *arts = (ArtsVoice *) hw;
ldebug ("arts_hw_fini\n");
arts_close_stream(arts->stream);
arts->stream_inited = 0;
if (arts->pcm_buf) {
qemu_free (arts->pcm_buf);
arts->pcm_buf = NULL;
}
}
static int arts_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
{
ArtsVoice *arts = (ArtsVoice *) hw;
struct arts_params req, obt;
assert(!arts->stream_inited);
req.fmt = AUD_to_artsfmt (fmt);
req.freq = freq;
req.nchannels = nchannels;
req.fragsize = conf.fragsize;
req.nfrags = conf.nfrags;
if (arts_open (&req, &obt, &arts->stream))
return -1;
arts->stream_inited = 1;
arts->paused = 0;
hw->freq = obt.freq;
hw->fmt = arts_to_audfmt (obt.fmt);
hw->nchannels = obt.nchannels;
arts->nfrags = obt.nfrags;
arts->fragsize = obt.fragsize;
hw->bufsize = obt.nfrags * obt.fragsize;
arts->pcm_buf = qemu_mallocz (hw->bufsize);
if (!arts->pcm_buf) {
arts_close_stream (arts->stream);
arts->stream_inited = 0;
return -1;
}
return 0;
}
static int arts_hw_ctl (HWVoice *hw, int cmd, ...)
{
ArtsVoice *arts = (ArtsVoice *) hw;
switch (cmd) {
case VOICE_ENABLE:
ldebug ("enabling voice\n");
pcm_hw_clear (hw, arts->pcm_buf, hw->samples);
arts->paused = 0;
break;
case VOICE_DISABLE:
ldebug ("disabling voice\n");
arts->paused = 0;
break;
}
return 0;
}
static void *arts_audio_init (void)
{
conf.fragsize = audio_get_conf_int (QC_ARTS_FRAGSIZE, conf.fragsize);
conf.nfrags = audio_get_conf_int (QC_ARTS_NFRAGS, conf.nfrags);
assert(!(arts_init() < 0));
return &conf;
}
static void arts_audio_fini (void *opaque)
{
arts_free();
}
struct pcm_ops arts_pcm_ops = {
arts_hw_init,
arts_hw_fini,
arts_hw_run,
arts_hw_write,
arts_hw_ctl
};
struct audio_output_driver arts_output_driver = {
"arts",
arts_audio_init,
arts_audio_fini,
&arts_pcm_ops,
1,
INT_MAX,
sizeof (ArtsVoice)
};
reply other threads:[~2005-07-11 2:56 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20050711023955.GA31186@jbrown.mylinuxbox.org \
--to=jma5@umd.edu \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).