@samitouri / QOSamiQemu / commits / c2dfd949cb

audio: add QOM module-objects for each backend

This will allow to use QOM and the dynamic object module loading. The changes are done systematically, introducing an empty instance structure that will later be filled by state with further refactoring. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>

Marc-André Lureau committed Oct 17, 2025 at 16:35 UTC c2dfd949cb81db70308b65b4bf911d98010ffe38
14 files changed +341
audio/alsaaudio.c
+27
@@ -27,6 +27,7 @@
27 #include "qemu/main-loop.h"
28 #include "qemu/module.h"
29 #include "qemu/audio.h"
30 +#include "qom/object.h"
31 #include "trace.h"
32
33 #pragma GCC diagnostic ignored "-Waddress"
@@ -36,6 +37,22 @@
37
38 #define DEBUG_ALSA 0
39
40 +#define TYPE_AUDIO_ALSA "audio-alsa"
41 +OBJECT_DECLARE_SIMPLE_TYPE(AudioALSA, AUDIO_ALSA)
42 +
43 +struct AudioALSA {
44 + AudioMixengBackend parent_obj;
45 +};
46 +
47 +static struct audio_driver alsa_audio_driver;
48 +
49 +static void audio_alsa_class_init(ObjectClass *klass, const void *data)
50 +{
51 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
52 +
53 + k->driver = &alsa_audio_driver;
54 +}
55 +
56 struct pollhlp {
57 snd_pcm_t *handle;
58 struct pollfd *pfds;
@@ -945,8 +962,18 @@ static struct audio_driver alsa_audio_driver = {
962 .voice_size_in = sizeof (ALSAVoiceIn)
963 };
964
965 +static const TypeInfo audio_alsa_info = {
966 + .name = TYPE_AUDIO_ALSA,
967 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
968 + .instance_size = sizeof(AudioALSA),
969 + .class_init = audio_alsa_class_init,
970 +};
971 +
972 +
973 static void register_audio_alsa(void)
974 {
975 audio_driver_register(&alsa_audio_driver);
976 + type_register_static(&audio_alsa_info);
977 }
978 type_init(register_audio_alsa);
979 +module_obj(TYPE_AUDIO_ALSA);
audio/audio_int.h
+2
@@ -241,6 +241,8 @@ struct SWVoiceCap {
241
242 struct AudioMixengBackendClass {
243 AudioBackendClass parent_class;
244 +
245 + audio_driver *driver;
246 };
247
248 struct AudioMixengBackend {
audio/coreaudio.m
+26
@@ -29,10 +29,27 @@
29 #include "qemu/main-loop.h"
30 #include "qemu/module.h"
31 #include "qemu/audio.h"
32 +#include "qom/object.h"
33
34 #define AUDIO_CAP "coreaudio"
35 #include "audio_int.h"
36
37 +#define TYPE_AUDIO_COREAUDIO "audio-coreaudio"
38 +OBJECT_DECLARE_SIMPLE_TYPE(AudioCoreaudio, AUDIO_COREAUDIO)
39 +
40 +struct AudioCoreaudio {
41 + AudioMixengBackend parent_obj;
42 +};
43 +
44 +static struct audio_driver coreaudio_audio_driver;
45 +
46 +static void audio_coreaudio_class_init(ObjectClass *klass, const void *data)
47 +{
48 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
49 +
50 + k->driver = &coreaudio_audio_driver;
51 +}
52 +
53 typedef struct coreaudioVoiceOut {
54 HWVoiceOut hw;
55 pthread_mutex_t buf_mutex;
@@ -673,8 +690,17 @@ static struct audio_driver coreaudio_audio_driver = {
690 .voice_size_in = 0
691 };
692
693 +static const TypeInfo audio_coreaudio_info = {
694 + .name = TYPE_AUDIO_COREAUDIO,
695 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
696 + .instance_size = sizeof(AudioCoreaudio),
697 + .class_init = audio_coreaudio_class_init,
698 +};
699 +
700 static void register_audio_coreaudio(void)
701 {
702 audio_driver_register(&coreaudio_audio_driver);
703 + type_register_static(&audio_coreaudio_info);
704 }
705 type_init(register_audio_coreaudio);
706 +module_obj(TYPE_AUDIO_COREAUDIO);
audio/dbusaudio.c
+26
@@ -26,6 +26,7 @@
26 #include "qemu/error-report.h"
27 #include "qemu/module.h"
28 #include "qemu/dbus.h"
29 +#include "qom/object.h"
30
31 #ifdef G_OS_UNIX
32 #include <gio/gunixfdlist.h>
@@ -44,6 +45,22 @@
45
46 #define DBUS_DEFAULT_AUDIO_NSAMPLES 480
47
48 +#define TYPE_AUDIO_DBUS "audio-dbus"
49 +OBJECT_DECLARE_SIMPLE_TYPE(AudioDbus, AUDIO_DBUS)
50 +
51 +struct AudioDbus {
52 + AudioMixengBackend parent_obj;
53 +};
54 +
55 +static struct audio_driver dbus_audio_driver;
56 +
57 +static void audio_dbus_class_init(ObjectClass *klass, const void *data)
58 +{
59 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
60 +
61 + k->driver = &dbus_audio_driver;
62 +}
63 +
64 typedef struct DBusAudio {
65 Audiodev *dev;
66 GDBusObjectManagerServer *server;
@@ -711,10 +728,19 @@ static struct audio_driver dbus_audio_driver = {
728 .voice_size_in = sizeof(DBusVoiceIn)
729 };
730
731 +static const TypeInfo audio_dbus_info = {
732 + .name = TYPE_AUDIO_DBUS,
733 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
734 + .instance_size = sizeof(AudioDbus),
735 + .class_init = audio_dbus_class_init,
736 +};
737 +
738 static void register_audio_dbus(void)
739 {
740 audio_driver_register(&dbus_audio_driver);
741 + type_register_static(&audio_dbus_info);
742 }
743 type_init(register_audio_dbus);
744
745 module_dep("ui-dbus")
746 +module_obj(TYPE_AUDIO_DBUS)
audio/dsoundaudio.c
+26
@@ -33,6 +33,7 @@
33 #include "audio_int.h"
34 #include "qemu/module.h"
35 #include "qapi/error.h"
36 +#include "qom/object.h"
37
38 #include <windows.h>
39 #include <mmsystem.h>
@@ -41,6 +42,22 @@
42
43 #include "audio_win_int.h"
44
45 +#define TYPE_AUDIO_DSOUND "audio-dsound"
46 +OBJECT_DECLARE_SIMPLE_TYPE(AudioDsound, AUDIO_DSOUND)
47 +
48 +struct AudioDsound {
49 + AudioMixengBackend parent_obj;
50 +};
51 +
52 +static struct audio_driver dsound_audio_driver;
53 +
54 +static void audio_dsound_class_init(ObjectClass *klass, const void *data)
55 +{
56 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
57 +
58 + k->driver = &dsound_audio_driver;
59 +}
60 +
61 /* #define DEBUG_DSOUND */
62
63 typedef struct {
@@ -694,8 +711,17 @@ static struct audio_driver dsound_audio_driver = {
711 .voice_size_in = sizeof (DSoundVoiceIn)
712 };
713
714 +static const TypeInfo audio_dsound_info = {
715 + .name = TYPE_AUDIO_DSOUND,
716 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
717 + .instance_size = sizeof(AudioDsound),
718 + .class_init = audio_dsound_class_init,
719 +};
720 +
721 static void register_audio_dsound(void)
722 {
723 audio_driver_register(&dsound_audio_driver);
724 + type_register_static(&audio_dsound_info);
725 }
726 type_init(register_audio_dsound);
727 +module_obj(TYPE_AUDIO_DSOUND);
audio/jackaudio.c
+26
@@ -27,6 +27,7 @@
27 #include "qemu/atomic.h"
28 #include "qemu/main-loop.h"
29 #include "qemu/audio.h"
30 +#include "qom/object.h"
31
32 #define AUDIO_CAP "jack"
33 #include "audio_int.h"
@@ -34,6 +35,22 @@
35 #include <jack/jack.h>
36 #include <jack/thread.h>
37
38 +#define TYPE_AUDIO_JACK "audio-jack"
39 +OBJECT_DECLARE_SIMPLE_TYPE(AudioJack, AUDIO_JACK)
40 +
41 +struct AudioJack {
42 + AudioMixengBackend parent_obj;
43 +};
44 +
45 +static struct audio_driver jack_driver;
46 +
47 +static void audio_jack_class_init(ObjectClass *klass, const void *data)
48 +{
49 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
50 +
51 + k->driver = &jack_driver;
52 +}
53 +
54 struct QJack;
55
56 typedef enum QJackState {
@@ -691,10 +708,18 @@ static void qjack_info(const char *msg)
708 dolog("I: %s\n", msg);
709 }
710
711 +static const TypeInfo audio_jack_info = {
712 + .name = TYPE_AUDIO_JACK,
713 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
714 + .instance_size = sizeof(AudioJack),
715 + .class_init = audio_jack_class_init,
716 +};
717 +
718 static void register_audio_jack(void)
719 {
720 qemu_mutex_init(&qjack_shutdown_lock);
721 audio_driver_register(&jack_driver);
722 + type_register_static(&audio_jack_info);
723 #if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
724 jack_set_thread_creator(qjack_thread_creator);
725 #endif
@@ -702,3 +727,4 @@ static void register_audio_jack(void)
727 jack_set_info_function(qjack_info);
728 }
729 type_init(register_audio_jack);
730 +module_obj(TYPE_AUDIO_JACK);
audio/noaudio.c
+26
@@ -25,10 +25,27 @@
25 #include "qemu/osdep.h"
26 #include "qemu/module.h"
27 #include "qemu/audio.h"
28 +#include "qom/object.h"
29
30 #define AUDIO_CAP "noaudio"
31 #include "audio_int.h"
32
33 +#define TYPE_AUDIO_NONE "audio-none"
34 +OBJECT_DECLARE_SIMPLE_TYPE(AudioNone, AUDIO_NONE)
35 +
36 +struct AudioNone {
37 + AudioMixengBackend parent_obj;
38 +};
39 +
40 +static struct audio_driver no_audio_driver;
41 +
42 +static void audio_none_class_init(ObjectClass *klass, const void *data)
43 +{
44 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
45 +
46 + k->driver = &no_audio_driver;
47 +}
48 +
49 typedef struct NoVoiceOut {
50 HWVoiceOut hw;
51 RateCtl rate;
@@ -138,8 +155,17 @@ static struct audio_driver no_audio_driver = {
155 .voice_size_in = sizeof (NoVoiceIn)
156 };
157
158 +static const TypeInfo audio_none_info = {
159 + .name = TYPE_AUDIO_NONE,
160 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
161 + .instance_size = sizeof(AudioNone),
162 + .class_init = audio_none_class_init,
163 +};
164 +
165 static void register_audio_none(void)
166 {
167 audio_driver_register(&no_audio_driver);
168 + type_register_static(&audio_none_info);
169 }
170 type_init(register_audio_none);
171 +module_obj(TYPE_AUDIO_NONE);
audio/ossaudio.c
+26
@@ -30,11 +30,28 @@
30 #include "qemu/host-utils.h"
31 #include "qapi/error.h"
32 #include "qemu/audio.h"
33 +#include "qom/object.h"
34 #include "trace.h"
35
36 #define AUDIO_CAP "oss"
37 #include "audio_int.h"
38
39 +#define TYPE_AUDIO_OSS "audio-oss"
40 +OBJECT_DECLARE_SIMPLE_TYPE(AudioOss, AUDIO_OSS)
41 +
42 +struct AudioOss {
43 + AudioMixengBackend parent_obj;
44 +};
45 +
46 +static struct audio_driver oss_audio_driver;
47 +
48 +static void audio_oss_class_init(ObjectClass *klass, const void *data)
49 +{
50 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
51 +
52 + k->driver = &oss_audio_driver;
53 +}
54 +
55 #if defined OSS_GETVERSION && defined SNDCTL_DSP_POLICY
56 #define USE_DSP_POLICY
57 #endif
@@ -772,8 +789,17 @@ static struct audio_driver oss_audio_driver = {
789 .voice_size_in = sizeof (OSSVoiceIn)
790 };
791
792 +static const TypeInfo audio_oss_info = {
793 + .name = TYPE_AUDIO_OSS,
794 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
795 + .instance_size = sizeof(AudioOss),
796 + .class_init = audio_oss_class_init,
797 +};
798 +
799 static void register_audio_oss(void)
800 {
801 audio_driver_register(&oss_audio_driver);
802 + type_register_static(&audio_oss_info);
803 }
804 type_init(register_audio_oss);
805 +module_obj(TYPE_AUDIO_OSS);
audio/paaudio.c
+26
@@ -4,12 +4,29 @@
4 #include "qemu/module.h"
5 #include "qemu/audio.h"
6 #include "qapi/error.h"
7 +#include "qom/object.h"
8
9 #include <pulse/pulseaudio.h>
10
11 #define AUDIO_CAP "pulseaudio"
12 #include "audio_int.h"
13
14 +#define TYPE_AUDIO_PA "audio-pa"
15 +OBJECT_DECLARE_SIMPLE_TYPE(AudioPa, AUDIO_PA)
16 +
17 +struct AudioPa {
18 + AudioMixengBackend parent_obj;
19 +};
20 +
21 +static struct audio_driver pa_audio_driver;
22 +
23 +static void audio_pa_class_init(ObjectClass *klass, const void *data)
24 +{
25 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
26 +
27 + k->driver = &pa_audio_driver;
28 +}
29 +
30 typedef struct PAConnection {
31 char *server;
32 int refcount;
@@ -931,8 +948,17 @@ static struct audio_driver pa_audio_driver = {
948 .voice_size_in = sizeof (PAVoiceIn),
949 };
950
951 +static const TypeInfo audio_pa_info = {
952 + .name = TYPE_AUDIO_PA,
953 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
954 + .instance_size = sizeof(AudioPa),
955 + .class_init = audio_pa_class_init,
956 +};
957 +
958 static void register_audio_pa(void)
959 {
960 audio_driver_register(&pa_audio_driver);
961 + type_register_static(&audio_pa_info);
962 }
963 type_init(register_audio_pa);
964 +module_obj(TYPE_AUDIO_PA);
audio/pwaudio.c
+26
@@ -13,6 +13,7 @@
13 #include "qemu/audio.h"
14 #include "qemu/error-report.h"
15 #include "qapi/error.h"
16 +#include "qom/object.h"
17 #include <spa/param/audio/format-utils.h>
18 #include <spa/utils/ringbuffer.h>
19 #include <spa/utils/result.h>
@@ -27,6 +28,22 @@
28
29 #include "audio_int.h"
30
31 +#define TYPE_AUDIO_PW "audio-pipewire"
32 +OBJECT_DECLARE_SIMPLE_TYPE(AudioPw, AUDIO_PW)
33 +
34 +struct AudioPw {
35 + AudioMixengBackend parent_obj;
36 +};
37 +
38 +static struct audio_driver pw_audio_driver;
39 +
40 +static void audio_pw_class_init(ObjectClass *klass, const void *data)
41 +{
42 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
43 +
44 + k->driver = &pw_audio_driver;
45 +}
46 +
47 typedef struct pwvolume {
48 uint32_t channels;
49 float values[SPA_AUDIO_MAX_CHANNELS];
@@ -847,10 +864,19 @@ static struct audio_driver pw_audio_driver = {
864 .voice_size_in = sizeof(PWVoiceIn),
865 };
866
867 +static const TypeInfo audio_pw_info = {
868 + .name = TYPE_AUDIO_PW,
869 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
870 + .instance_size = sizeof(AudioPw),
871 + .class_init = audio_pw_class_init,
872 +};
873 +
874 static void
875 register_audio_pw(void)
876 {
877 audio_driver_register(&pw_audio_driver);
878 + type_register_static(&audio_pw_info);
879 }
880
881 type_init(register_audio_pw);
882 +module_obj(TYPE_AUDIO_PW);
audio/sdlaudio.c
+26
@@ -28,6 +28,7 @@
28 #include "qemu/module.h"
29 #include "qapi/error.h"
30 #include "qemu/audio.h"
31 +#include "qom/object.h"
32
33 #ifndef _WIN32
34 #ifdef __sun__
@@ -40,6 +41,22 @@
41 #define AUDIO_CAP "sdl"
42 #include "audio_int.h"
43
44 +#define TYPE_AUDIO_SDL "audio-sdl"
45 +OBJECT_DECLARE_SIMPLE_TYPE(AudioSdl, AUDIO_SDL)
46 +
47 +struct AudioSdl {
48 + AudioMixengBackend parent_obj;
49 +};
50 +
51 +static struct audio_driver sdl_audio_driver;
52 +
53 +static void audio_sdl_class_init(ObjectClass *klass, const void *data)
54 +{
55 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
56 +
57 + k->driver = &sdl_audio_driver;
58 +}
59 +
60 typedef struct SDLVoiceOut {
61 HWVoiceOut hw;
62 int exit;
@@ -491,8 +508,17 @@ static struct audio_driver sdl_audio_driver = {
508 .voice_size_in = sizeof(SDLVoiceIn),
509 };
510
511 +static const TypeInfo audio_sdl_info = {
512 + .name = TYPE_AUDIO_SDL,
513 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
514 + .instance_size = sizeof(AudioSdl),
515 + .class_init = audio_sdl_class_init,
516 +};
517 +
518 static void register_audio_sdl(void)
519 {
520 audio_driver_register(&sdl_audio_driver);
521 + type_register_static(&audio_sdl_info);
522 }
523 type_init(register_audio_sdl);
524 +module_obj(TYPE_AUDIO_SDL);
audio/sndioaudio.c
+26
@@ -20,10 +20,27 @@
20 #include "qemu/main-loop.h"
21 #include "qemu/audio.h"
22 #include "trace.h"
23 +#include "qom/object.h"
24
25 #define AUDIO_CAP "sndio"
26 #include "audio_int.h"
27
28 +#define TYPE_AUDIO_SNDIO "audio-sndio"
29 +OBJECT_DECLARE_SIMPLE_TYPE(AudioSndio, AUDIO_SNDIO)
30 +
31 +struct AudioSndio {
32 + AudioMixengBackend parent_obj;
33 +};
34 +
35 +static struct audio_driver sndio_audio_driver;
36 +
37 +static void audio_sndio_class_init(ObjectClass *klass, const void *data)
38 +{
39 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
40 +
41 + k->driver = &sndio_audio_driver;
42 +}
43 +
44 /* default latency in microseconds if no option is set */
45 #define SNDIO_LATENCY_US 50000
46
@@ -555,9 +572,18 @@ static struct audio_driver sndio_audio_driver = {
572 .voice_size_in = sizeof(SndioVoice)
573 };
574
575 +static const TypeInfo audio_sndio_info = {
576 + .name = TYPE_AUDIO_SNDIO,
577 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
578 + .instance_size = sizeof(AudioSndio),
579 + .class_init = audio_sndio_class_init,
580 +};
581 +
582 static void register_audio_sndio(void)
583 {
584 audio_driver_register(&sndio_audio_driver);
585 + type_register_static(&audio_sndio_info);
586 }
587
588 type_init(register_audio_sndio);
589 +module_obj(TYPE_AUDIO_SNDIO);
audio/spiceaudio.c
+26
@@ -24,11 +24,28 @@
24 #include "qemu/timer.h"
25 #include "qapi/error.h"
26 #include "ui/qemu-spice.h"
27 +#include "qom/object.h"
28
29 #define AUDIO_CAP "spice"
30 #include "qemu/audio.h"
31 #include "audio_int.h"
32
33 +#define TYPE_AUDIO_SPICE "audio-spice"
34 +OBJECT_DECLARE_SIMPLE_TYPE(AudioSpice, AUDIO_SPICE)
35 +
36 +struct AudioSpice {
37 + AudioMixengBackend parent_obj;
38 +};
39 +
40 +static struct audio_driver spice_audio_driver;
41 +
42 +static void audio_spice_class_init(ObjectClass *klass, const void *data)
43 +{
44 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
45 +
46 + k->driver = &spice_audio_driver;
47 +}
48 +
49 #if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3
50 #define LINE_OUT_SAMPLES (480 * 4)
51 #else
@@ -325,10 +342,19 @@ static struct audio_driver spice_audio_driver = {
342 .voice_size_in = sizeof (SpiceVoiceIn),
343 };
344
345 +static const TypeInfo audio_spice_info = {
346 + .name = TYPE_AUDIO_SPICE,
347 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
348 + .instance_size = sizeof(AudioSpice),
349 + .class_init = audio_spice_class_init,
350 +};
351 +
352 static void register_audio_spice(void)
353 {
354 audio_driver_register(&spice_audio_driver);
355 + type_register_static(&audio_spice_info);
356 }
357 type_init(register_audio_spice);
358 +module_obj(TYPE_AUDIO_SPICE);
359
360 module_dep("ui-spice-core");
audio/wavaudio.c
+26
@@ -25,10 +25,27 @@
25 #include "qemu/osdep.h"
26 #include "qemu/module.h"
27 #include "qemu/audio.h"
28 +#include "qom/object.h"
29
30 #define AUDIO_CAP "wav"
31 #include "audio_int.h"
32
33 +#define TYPE_AUDIO_WAV "audio-wav"
34 +OBJECT_DECLARE_SIMPLE_TYPE(AudioWav, AUDIO_WAV)
35 +
36 +struct AudioWav {
37 + AudioMixengBackend parent_obj;
38 +};
39 +
40 +static struct audio_driver wav_audio_driver;
41 +
42 +static void audio_wav_class_init(ObjectClass *klass, const void *data)
43 +{
44 + AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
45 +
46 + k->driver = &wav_audio_driver;
47 +}
48 +
49 typedef struct WAVVoiceOut {
50 HWVoiceOut hw;
51 FILE *f;
@@ -214,8 +231,17 @@ static struct audio_driver wav_audio_driver = {
231 .voice_size_in = 0
232 };
233
234 +static const TypeInfo audio_wav_info = {
235 + .name = TYPE_AUDIO_WAV,
236 + .parent = TYPE_AUDIO_MIXENG_BACKEND,
237 + .instance_size = sizeof(AudioWav),
238 + .class_init = audio_wav_class_init,
239 +};
240 +
241 static void register_audio_wav(void)
242 {
243 audio_driver_register(&wav_audio_driver);
244 + type_register_static(&audio_wav_info);
245 }
246 type_init(register_audio_wav);
247 +module_obj(TYPE_AUDIO_WAV);